Atlantic Business Technologies, Inc.

Category: .NET

  • Tools to Help Build APIs

    Tools to Help Build APIs

    One of the most common types of development work done at Atlantic BT is building APIs. An API (Application Programming Interface) is a set of defined rules that allow different software applications to communicate and share data with each other. The APIs we develop at Atlantic BT are used not only by the websites we create, but by external clients and third-party services. Therefore, defining, documenting, and testing these APIs is a critical part of our process. This blog post will showcase several helpful tools that we use while building APIs for our clients.

    Defining and Documenting APIs

    Defining and documenting your API is an important step when building and maintaining an API. Regardless of whether the consumer of your API is an internal or external user, having a clear understanding of how to interact with your API is essential for making the development process as smooth as possible. Fortunately, there exists a suite of tools to help with this.

    Swagger

    https://swagger.io

    Swagger (referred interchangeably with Open API) is a standard, programming language independent way to describe APIs. When defining your API, you create an Open API specification that describes your API’s endpoints, input/output parameters, and authentication methods. This specification can then be used to generate interactive documentation and client SDKs.

    Swashbuckle 

    https://github.com/domaindrivendev/Swashbuckle.AspNetCore

    Swashbuckle is a .NET library that automatically generates Open API standard documentation from your existing API code and provides a user-friendly UI for testing them. This is great for legacy applications that may be missing documentation. With minimal code, Swagger documentation can be generated, giving developers and API users specifications that would otherwise take considerable time to write and maintain. While Swashbuckle is a .NET specific library, there exists comparable tools made in almost every language.

    SwaggerHub

    https://app.swaggerhub.com

    SwaggerHub is a collaborative platform designed for API development that leverages the Swagger/OpenAPI standard. It provides a centralized place to manage and version your API documentation. At Atlantic BT, we use SwaggerHub when building APIs that need to be consumed by our clients. This allows everyone involved to always have the latest API definition, which makes collaboration with our clients much more efficient.

    Testing APIs

    Once your API has been defined, and development has started, testing that API becomes the focus to ensure it is functioning as expected. Once again, there exists a variety of tools to help with this important step.

    Postman

    https://www.postman.com

    Postman is an API testing tool that offers a user-friendly interface for making requests and viewing responses. It allows you to save and organize your requests in collections, which helps if you work on multiple APIs or work with many clients, as we do at Atlantic BT. It allows simple control over the headers and body of the request, which make it our preferred tool when we quickly need to test out an API endpoint. 

    Webhook.site

    https://webhook.site

    One of the common scenarios that leads us to develop an API for our clients is to receive data from a webhook on a third-party site. A webhook is a method used to send notifications to other systems by making an HTTP request to a specified URL whenever a particular event occurs. When developing this webhook API endpoint, the problem is that the computer you use to do development work on often isn’t publicly accessible by the site sending the API request. So how are you supposed to know what the webhook data looks like? One way to solve this problem is using Webhook.site

    Webhook.site gives you a unique publicly available URL that you can have a site send requests to. In addition, it has a simple interface that allows you to view all the requests that are sent to that unique URL. You can then copy the request data that was sent and paste it into Postman running on your computer to send to your in development API.

    ngrok

    https://ngrok.com

    Another solution to testing a webhook is to use ngrok. ngrok is a tool that runs on your computer and creates a secure tunnel from a public URL to your local machine. This allows you to expose and test your local API over the internet. Using ngrok will let you test the full flow of the webhook without having to use the extra steps of having data sent to Webhook.site and then sending the data again using Postman. ngrok also allows you to inspect and replay requests, which is helpful so you don’t have to trigger the webhook repeatedly.

    Conclusion

    Whether an API is public-facing or behind the scenes, it is an integral part of modern web development. Regardless of the purpose of the API, documenting and testing are key steps in our software development process at Atlantic BT. And with the help of the above-mentioned tools, it allows us to be more detailed, rigorous, and consistent when building and maintaining APIs for our clients.

  • Five reasons to outsource your software development project.

    Five reasons to outsource your software development project.

    There are many scenarios where it could make sense to outsource a software project. But first, let’s clarify the difference between outsourced development and offshore development.

    You could outsource to an offshore firm. You could also outsource to a company in your backyard. In this post we are talking about partnering with a software development agency in your backyard, not overseas. 

    Here are a few reasons outsourcing might be the smarter and easier route.

    1. Your team lacks the technical skills needed for this project.

    Although It would be convenient if all programmers had the qualifications to work on all projects, that’s far from reality. Each developer has a unique set of technical skills and experiences. You could have many highly-qualified and capable people on your team. But that does not guarantee that they are a good fit to build the kind of software you need at the moment. By turning to an outsourced team, you can find teams that specialize in exactly what you’re looking for. When you’re positive you’ll get the specific knowledge needed for the job, you lower your risk of missing deadlines and making mistakes.

    2. A new project could derail your busy team.

    In other cases, your software development team may have the right background needed for your project. But companies with in-house programmers usually have many ongoing needs. Your team may not have time in their schedule to give the project necessary attention and care.

    Or maybe your team is focused on other features and don’t want to do the upkeep or grunt work on a new application. Adding a large job on top of existing duties can slow down work on critical tasks. It can also leave your new development project in a perpetual purgatory. On the other hand, let’s say your programmers do have the time to tackle the new project. Do they have expertise in using new tools? Buying necessary tools to complete a new project and training your software development team is costly.

    3. You need the project finished on a tight deadline.

    An outsourced programming team is your best bet when you need a new piece of software finished yesterday. They have the ability to devote a specific group of developers to the job and on your schedule. 

    When you outsource a project, it is with the intent that the team you’ve hired focuses on your deadline. They’ll go to work knowing that time is of the essence and a vital part of making the project a success.

    And let’s not forget about money as motivation. Your outsourced team is working under different financial parameters than your in-house programmers. Payment is dependent on a successful project completed on time.

    Your in-house programmers are most likely salaried and not facing the same pressure. In other words, a vendor has more incentives to work at the pace you need than your salaried employees might.

    4. You want an outsourced perspective on the project.

    Deciding to outsource your software development project brings about many benefits, aside from providing you with extra hands to do the work. You also get the benefit of many years experience and a new perspective. Your vendor has, thus far, not been a part of the process. They weren’t in the same meetings. They can see the project through the lens of their own expertise, finding patterns over time. They know the causes of your pain and can help you avoid common pitfalls.Your vendor can also look at the merits and constraints of the job with a more critical eye. This allows them to ask better questions and give more productive feedback. The result will be a stronger app or piece of software. The project will not only meet your standards, they will exceed them

    5. You need user experience perspective.

    Let’s face it, software developers are great at writing code and all the fancy DevOps automation, but they often lack the necessary empathy to be critical of the user experience they are creating. A critical step to deliver a satisfactory UX will involve bringing in an outside team to provoke conversations. Have structured conversations around how the user interface and user experience are impacting the software and ultimately business value.Outsourcing software development can reduce stress.It’s always great to have your own team of trusted and talented programmers in your company, but you don’t have to rely on them for every project. In fact, letting a partner handle excess can create focus and boost employee happiness. We’re always game for any type of project thrown our way. Learn more about our process and reach out. We’d be glad to have a more in-depth conversation about your specific needs and what we can do to help.

  • Deploying a .NET Core API to AWS Lambda & API Gateway using Bitbucket

    Deploying a .NET Core API to AWS Lambda & API Gateway using Bitbucket

    After a transition to Bitbucket for our repository hosting last year, we’ve been setting up more and more CI/CD using Bitbucket Pipelines. I recently converted a .NET Core API project that was deploying to an auto-scaling group of EC2s into a project that could be deployed in AWS Lambda behind API Gateway using Bitbucket. The web project that consumes this API is written in Angular.

    As a shop that leverages automated deployments in multiple environments, I found documentation on the web to be in short supply other than very basic “deploy using VS Studio” articles.

    As part of updating the API project to Lambda, I did make my LambdaEntryPoint reference APIGatewayHttpApiV2ProxyFunction and the serverless template event of type HttpApi. A guide to these updates can found here: One Month Update to .NET Core 3.1 Lambda

    In this post, I provide some snippets of YAML code which I found out in the world that didn’t work, and also what ultimately did.

    Jump to What Worked

    What Didn’t Work

    aws-sam-deploy

    caches:
      - dotnetcore
    steps:
      - export PROJECT_NAME=this-dotnet-project
      - dotnet restore
      - dotnet build $PROJECT_NAME
      - pipe: atlassian/aws-sam-deploy:1.5.0

    When trying to use the aws-sam-deploy pipe, I wasn’t able to leverage enough options or get the API to run the .NET code successfully. The API Gateway endpoint was running and hitting Lambda, but I was getting system errors I just couldn’t resolve.

    Using project appsettings files

    Since appsettings.json files contains secrets, we don’t check them into the repo. At some point I was receiving these errors, and I realized that the appsettings files weren’t getting deployed correctly.

    run_dotnet(dotnet_path, &args) failed
    
    Could not find the required 'this-dotnet-project.deps.json'. This file should be present at the root of the deployment package.: LambdaException

    We ended up injecting the appsettings content using the AWS Parameter Store with aws ssm get-parameter.

    dotnet publish, zip, and aws-lambda-deploy

    - apt-get update && apt-get install --yes zip
    - dotnet restore
    - dotnet publish ${API_PROJECT_NAME} --output "./publish"  --framework "netcoreapp3.1" /p:GenerateRuntimeConfigurationFiles=true --runtime linux-x64 --self-contained false
    - curl -o /bin/jp -L https://github.com/jmespath/jp/releases/download/0.1.3/jp-linux-amd64 && chmod a+x /bin/jp
    - aws ssm get-parameter --name "/this-project/api/dev/appsettings" --with-decryption --region us-east-1 | /bin/jp -u "Parameter.Value" | base64 -d > ./publish/appsettings.json
    - zip -r -j package.zip publish/*         
    - pipe: atlassian/aws-lambda-deploy:1.5.0
      variables:
         AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
         AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
         AWS_DEFAULT_REGION: ${AWS_REGION}
         FUNCTION_NAME: "this-dotnet-project-AspNetCoreFunction-LZj5pbvV0GRT"
         COMMAND: "update"
         ZIP_FILE: "$BITBUCKET_CLONE_DIR/package.zip"

    We have some single Lambda functions (not behind API Gateway) that use this method for deploying. It works great. I tried using this method pushing to a function that was built with a stack published via VS Studio. No luck. It’s possible there was a problem with the stack that was built, but I think this package wasn’t exactly right.

    What Works

    The following is the pipeline for a single branch, our develop branch. I haven’t yet refactored using template steps, but this is easier to read through for this article anyway.

    I have scrubbed the contents of this YAML, but the repo contains:

    • Root (.sln file)
      • .Net Core API project directory (named this-dotnet-project here)
      • Angular web project directory (named this-web-project here)
    pipelines:  
      branches:
        develop:
          - step:
              name: API (.Net Core) Build & Deploy 
              image: mcr.microsoft.com/dotnet/core/sdk:3.1
              deployment: Develop
              script:
              - apt-get update && apt-get install -y zip && apt-get install -y awscli
              - dotnet tool install -g Amazon.Lambda.Tools
              - export PATH="$PATH:/root/.dotnet/tools"
              - curl -o /bin/jp -L https://github.com/jmespath/jp/releases/download/0.1.3/jp-linux-amd64 && chmod a+x /bin/jp
              - aws ssm get-parameter --name "/this-project/api/dev/appsettings" --with-decryption --region us-east-1 | /bin/jp -u "Parameter.Value" | base64 -d > ./this-dotnet-project/appsettings.json
              - cd this-dotnet-project/
              - dotnet lambda deploy-serverless --aws-access-key-id ${AWS_ACCESS_KEY_ID} --aws-secret-key ${AWS_SECRET_ACCESS_KEY} --region ${AWS_REGION} --configuration "Development" --framework "netcoreapp3.1" --runtime linux-x64 --s3-bucket $API_S3_BUCKET --stack-name $API_STACK_NAME --stack-wait true
          - step:
              name: Web (Angular) Build
              image: atlassian/default-image:2
              caches:
              - node
              script:
    	      - cd this-web-project #The angular project is currently in a subfolder in the same repo
              - nvm install 12
              - nvm use 12
              - npm install @angular/cli
              - npm run build:dev
              artifacts: # defining the artifacts to be passed to each future step.
              - dist/**
          - step:
              name: Web (Angular) Deploy
              script:
              - pipe: atlassian/aws-s3-deploy:0.5.0
                variables:
                  AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID} 
                  AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
                  AWS_DEFAULT_REGION: ${AWS_REGION}
                  S3_BUCKET: ${WEB_S3_BUCKET_DEV}
                  LOCAL_PATH: "this-web-project/dist/this-project-output-path/"

    apt-get install and dotnet tool install

    Items that were quickly apparent as missing before adding them, more of a “duh” leaving them out when trying so many things.

    dotnet lambda deploy-serverless

    This was the big command that mostly got things working. I finally found this is effectively what’s happening when you deploy the API project from VS Studio.

    –stack-wait true

    In Bitbucket, without this, the build shows as successful when the stack build is kicked off. By adding this flag, bitbucket will wait for the full build or update before continuing.

  • Is Umbraco the best option for my website?

    Is Umbraco the best option for my website?

    Umbraco is an open-source CMS running on the .NET framework. It has been and remains the front runner for a .NET CMS.

    Umbraco is the ideal solution for highly customized and unique applications. This is an enterprise solution that leaves you open to endless possibilities. For example, access some of the highest tier plugins and software packages available for .NET.

    First of all, review the key features of Umbraco.

     

    • It’s free to use. While the open-source platform is free, your .NET team may require you purchase some plugins to facilitate development.
    • Work in a simple UI. Creating and building pages in Umbraco was designed to be intuitive. Minimal training is needed to get users familiar with entering content in the CMS, and no HTML experience is needed.

    • You have multiple options for building content. Choose from the following editing experiences with content layouts:

    1. Grid layouts: This option is for maximum freedom. A Row/Column builder that lets you freely enter content or insert custom components in basically any configuration.
    2. Band system or component picker: Select various components to put together pages.
    3. Strict property entry: Don’t worry about layout – simply enter content into fields on pre-styled pages.
    • Rely on a robust hosting option. Umbraco can handle the hosting of large content bases, including many pages and catalogs of content. It can be self-hosted on windows servers, or you may use Umbraco’s own cloud hosting. Hosting is built with load balancing at its core, perfect for multi server load balanacing.

    • It’s easy for developers to use. Umbraco makes it easy for developers to set up and manage page types, templates, content, and plugins. This saves money on development time and maintenance (with a cleaner code base).

    • Upgrades are simple. Umbraco has recently focused on improving upgrades. Most are automated, and others have instructions for manual changes.
    • Umbraco includes vast functionality and community support:
      • Multi-user and role support
      • Simple multilingual management
      • Easy-to-use form builders
      • Powerful search based on the lucene framework
      • Content migration features
      • Open source and well documented API
      • Large, active development community provides support
     

    When should I use Umbraco?

    Umbraco is a robust base for advanced applications. It’s a great option if you can take advantage of enterprise-level software development tools and frameworks in your business model. Here are some other scenarios where you would benefit from Umbraco.

    You have access to .NET resources.

    The most obvious reason to use Umbraco is if you have a .NET team available. Or maybe you already have an existing .NET application, and you wish to retain some of the existing code base.

    Umbraco works like a standard .NET project, so any existing .NET libraries are easily imported.

    Multilingual support is a requirement.

    Managing multiple languages is easy with Umbraco. It includes a simple multilingual UI with translation capabilities.

    Users and roles have complex definitions.

    If your project needs multiple admin roles to manage content, then Umbraco might be the best option for you. That’s because users and roles can be setup for very granular access to pages and features.

    The application requires a functionally that only works with Windows.

    For example, you may prefer to use Active Directory for authentication, which is a proprietary windows-based software.

    When should I not use Umbraco?

    The website has a simple purpose.

    A simple brochure website with no expectation for expanding doesn’t need a robust option. Umbraco would likely be overkill.

    Hosting cost is a concern.

    While development cost with Umbraco should be similar to other CMS frameworks, hosting costs will be much higher.

    Advanced eCommerce is the primary focus.

    Building an eCommerce site with Umbraco is possible, but it’s not as simple as other platforms. For example, you would have to custom code an integration into a checkout process whereas other platforms have standard eCommerce features built in.

    There are rare occassions where Umbraco is necessary for eCommerce. At Atlantic BT, we have worked with an eLearning company that had a unique course checkout process. Purchasing a course requires entering student information which gets passed to a custom enrollment processor. Students can also use a prepaid method, where they would enter a business name instead of a credit card.

    In general, these out-of-the-ordinary custom features are best developed in .NET.

    A team experienced in many platforms can guide you.

    Need help evaluating your situation and choosing the best platform? Reach out for a free consultation with one of our experts. We’re happy to help you get started with your solution.

  • Shared Google Authorization with an Angular site and .Net Core API.

    Shared Google Authorization with an Angular site and .Net Core API.

    There are many Angular tutorials for setting up websites using the Angular framework and .NET Core APIs. Likewise, there are many walkthroughs for integrating Google authentication with each. However, implementing these solutions separately yield the need to authenticate through Google twice, once for the angular site, once for the API.

    This article provides a solution that allows shared Google authorization through authentication on the angular site. To surpass the need to authenticate a second time, pass the token through a standard header to the API and use Google libraries to validate and authorize.

    Technology used in this Angular tutorial.

    This post assumes you’ve got the basic angular website and Web API projects running. This post will also likely be effective for any angular site 2+ or front end site where google authentication occurs. It should also work if your Web API project is Core 2+.

    The site I’m working with is designed to be exclusively authenticated through Google, however this method could be extended to handle multiple authentication formats (assuming there are .Net validation libraries for them or you write your own). Therefore, one other aspect to mention is that I am not storing any user data in a database.

    Using the Angular site, Google login, and local storage as a start.

    The primary goal is to make sure you have access to Google’s idToken after authentication. Using the angular-social-login default setup is pretty simple to get working. This is a pretty good article which also walks through setting up the Google App as part of this if you need. I can’t find the original post I followed, but this stackoverflow post shows storing the Google user/token in state for future calls.

    This code block (customauth.service.ts in the Angular site) just shows that on user subscription the user is stored in local storage:

      constructor(
        public authService: AuthService,
        public router: Router,
        public ngZone: NgZone // NgZone service to remove outside scope warning
      ) {
        // Setting logged in user in localstorage else null
        this.authService.authState.subscribe(user => {
          if (user) {
            this.userData = user;
            localStorage.setItem('user', JSON.stringify(this.userData));
            JSON.parse(localStorage.getItem('user'));
          } else {
            localStorage.setItem('user', null);
            JSON.parse(localStorage.getItem('user'));
          }
        });
      }
    
      // Sign in with Google
      GoogleAuth() {
        return this.authService.signIn(GoogleLoginProvider.PROVIDER_ID);
      }
    
      // Sign out
      SignOut() {
        return this.authService.signOut().then(() => {
          localStorage.removeItem('user');
          this.router.navigate(['/']);
        });
      }

    Options researched before finding the current solution.

    • The Microsoft standard way to handle google authentication. This is slick if you’re building an MVC site and need to allow Google auth, but I couldn’t find a way to allow sending over the token, as this generates and uses a cookie value with a Identity.External key.
    • JWT authorization is an option, but the tutorials got heavy quickly. Since I don’t need to store users or use Microsoft Identity, I blew past this.
    • A custom policy provider is another Microsft standard practice. There might be a better way to accomplish the solution using this approach, but I didn’t walk this path too far since I wasn’t using authentication through the .Net solution.

    The solution: a .Net Core custom authorize attribute.

    I used this stackoverflow post about custom auth attributes to hook up the solution. This is what allows the shared Google authorization using a standard authorization request header.

    Approach

    1. In Angular
      1. Build the Authorization header using the Google idToken.
      2. Pass the header for any authorize only API endpoints.
    2. In the web API
      1. Enable authorization
      2. Create a custom IAuthorizationFilter and TypeFilterAttribute
      3. Tag any controllers or endpoints with the custom attribute

    I provide code samples for these steps below.

    Angular API calls with an authorization header.

    The code in the api service (api.service.ts in Angular Site) grabs the id token from the user in local storage and passes it through the API call. If the user is logged out, this header isn’t passed.

    import { Injectable } from '@angular/core';
    import { HttpClient, HttpHeaders } from '@angular/common/http';
    import { SocialUser } from 'angularx-social-login';
    import { environment } from './../../environments/environment';
    
    export class ApiService {
      apiURL = environment.apiUrl;
      user: SocialUser;
      defaultHeaders: HttpHeaders;
    
      constructor(private httpClient: HttpClient) {
        this.user = JSON.parse(localStorage.getItem('user'));
        this.defaultHeaders = new HttpHeaders();
        this.defaultHeaders = this.defaultHeaders.append('Content-Type', 'application/json');
        if (this.user != null) {
          this.defaultHeaders = this.defaultHeaders.append('Authorization', 'Bearer ' + this.user.idToken);
        }
      }
    
      public getAccounts() {
        const accounts = this.httpClient.get<Account[]>(`${this.apiURL}/accounts`, { headers: this.defaultHeaders });
        return accounts;
      }
    }

    Enabling authorization in the .Net Core project.

    In the StartUp file (StartUp.cs in the API project), authorization has to be enabled.

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
      ...
      app.UseRouting();
      app.UseAuthorization();
      app.UseEndpoints(endpoints =>
      {
          endpoints.MapControllers();
      });
    }

    The custom filter attribute to validate without another authorization.

    This creates the attribute used for authorization and performs a Google validation on the token.

    This application is used only for our Google G Suite users, and thus the “HostedDomain” option of the ValidationSettings is set. This isn’t necessary, and I believe can just be removed if you allow any Google user to authenticate.

    I’ve named this file GoogleAuthorizationFilter.cs in the API project.

    using Google.Apis.Auth;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.Filters;
    using System;
    
    namespace YourNamespace.API.Attributes
    {
        /// <summary>
        /// Custom Google Authentication authorize attribute which validates the bearer token.
        /// </summary>
        public class GoogleAuthorizeAttribute : TypeFilterAttribute
        {
            public GoogleAuthorizeAttribute() : base(typeof(GoogleAuthorizeFilter)) { }
        }
    
    
        public class GoogleAuthorizeFilter : IAuthorizationFilter
        {
    
            public GoogleAuthorizeFilter()
            {
            }
    
            public void OnAuthorization(AuthorizationFilterContext context)
            {
                try
                {
                    // Verify Authorization header exists
                    var headers = context.HttpContext.Request.Headers;
                    if (!headers.ContainsKey("Authorization"))
                    {
                        context.Result = new ForbidResult();
                    }
                    var authHeader = headers["Authorization"].ToString();
    
                    // Verify authorization header starts with bearer and has a token
                    if (!authHeader.StartsWith("Bearer ") && authHeader.Length > 7)
                    {
                        context.Result = new ForbidResult();
                    }
    
                    // Grab the token and verify through google. If verification fails, and exception will be thrown.
                    var token = authHeader.Remove(0, 7);
                    var validated = GoogleJsonWebSignature.ValidateAsync(token, new GoogleJsonWebSignature.ValidationSettings()
                    {
                        HostedDomain = "yourdomain.com",
                    }).Result;
                }
                catch (Exception)
                {
                    context.Result = new ForbidResult();
                }
            }
        }
    }
    

    Putting the custom attribute in place.

    This is just a snippet of code, as on your controllers you just have to add the one line of code (well, two including the using statement). If the GoogleAuthorize doesn’t validate, the call returns as access denied.

    using YourNamespace.API.Attributes;
    
    [GoogleAuthorize]
    [ApiController]
    public class AccountsController : BaseController {
    

    Voila! No need for a second authentication.

    The .Net API is now locked down only to requests originating from a site with Google authentication. The custom attribute can be extended for additional authentication sources or any other desired restrictions using the request. I like the simplicity of a site which allows Google auth only, but it wouldn’t be a stretch to add others – and I really like not managing any users or passwords. I hope this Angular tutorial for shared Google authentication works well for you too!

  • How Much Does it Cost to Build & Maintain a Web Application?

    How much does a custom web application cost to build and host? If you are reading this article you are probably trying to figure out if the application you need can be built at an affordable cost. Use this guide as a web application cost calculator. While there are many variables that can impact cost, the key factors generally fall into three categories: 1) size and complexity, 2) refinements and constraints, and 3) hosting and maintenance. 

    Start with the basics: how to determine size and complexity.

    To determine the size and complexity of your application we need to first define what it’s going to do. The specifications for modern software are often defined by ‘user stories’. These user stories are a simple way to describe discrete functionalities your application should provide, from an end-user perspective, and are often used by developers to define and estimate the effort required to build an application. 

    Let’s use Facebook as an example of a web-based application that most people are familiar with. While Facebook may seem relatively simple to use, it is actually a massive web application with many different functionalities for different users. Describing it in user stories would take a very long time, however, if we stick to its most basic functionality we can use it as a good example. Here are some examples of web-based user stories:

    • As a user, I need to register and create a profile
    • As a user, I need to verify my email address to complete my registration
    • As a user, I need to find friends to connect with
    • As a user, I need to request to connect with friends I find
    • As a user, I need to add pictures to my timeline
    • As a user, I need to post status updates to my timeline
    • As a user, I need to browse my feed from other friends
    • As a user, I need to be able to react (like, love, hate, cry, etc) to posts on my feed
    • As a user, I need to be able to comment on posts on my feed
    • As an advertiser, I need to compare the performance of my campaigns
    • As an organizational social media manager, I need to manage roles for my page

    I think you get the idea. Defining this application in user stories would take a very long time, and producing each piece of application functionality takes a lot longer! With the table below we will try to ballpark the relative size of your application using the number of user stories. When you are thinking of your user stories also think of the relative complexity of each user story. For example: ‘As an advertiser, I need to compare the performance of my campaigns.’ is not the same level of effort as ‘As a user, I need to be able to react to posts on my feed.’ 

    We normally apply a ‘level of effort’ attribute to each user story to help scope the application. In development ‘low’ might mean 5-10 hours, ‘medium’ 10 to 20, and ‘hard’ 50 to 100. Any user story more complex than that should be broken down into smaller stories. For example ‘As a user, I need to manage my profile’ is not an acceptable user story and should be broken down into even smaller pieces.

    Micro (< $50,000) Small($50,000-$200,000) Medium($200,000-$1M) Large($1M+)
    10-15 “low effort” user stories 25-50 “low effort” user stories 50-100 “low effort” user stories 200+ “low effort” user stories
    5-10 “medium effort” user stories 10-25 “medium effort” user stories 25-50 “medium effort” user stories 50+ “medium effort” user stories
    1-2 “large effort” user stories 2-5 “large effort” user stories 10-20 “large effort” user stories 25+ “large effort” user stories

    What’s next? Identify application refinements and constraints.

    With any web application development, you must not only consider what your basic functional requirements are, but also include user expectations and behaviors, i.e. usability, and other constraints such as mission criticality and regulatory requirements in your industry.

    Gain a competitive edge by considering user delight.

    With any application you build, you are most likely facing competition in one form or another – in many cases direct competition, but even if not that, you are competing with your users’ expectations of what an efficient and pleasant web interaction feels like. That being the case, you want to refine your application to not only beat the competition but to also be a joy to use. Therefore, you will probably want to pay attention to usability in the design of your application. Software developers often have a basic idea of usability when developing software, but there’s a big difference between a software interface that basically functions and an efficient experience developed by a UI/UX professional. Here are a few classic UX design failures to illustrate the point.

    Good usability is best built into the design and informed by user research. To add a UX professional or team to your software project might add another DevOps chain5-10% (could be more depending on the nature of the application and how important the experience is). That said, this 5-10% can save you much more down the road in avoided rework and enhanced customer satisfaction and retention.

    Criticality, security, and regulatory requirements directly impact application cost.

    Is your application critical to the daily operation and success of your business, or that of others? Does it deal with health and safety or finance? Does it deal with an industry with regulatory requirements, such as PCI or HIPAA? Do federal accessibility requirements apply? If you answer yes to any of these questions, your application needs to be developed with special requirements in mind.

    All of these considerations will increase your budget significantly; not only through the additional requirements, but also due to the need for testing. All well-developed software is tested continually through the development process with both automated testing and human testing and peer review. Software that is extremely sensitive or critical would have additional layers of testing and security added throughout the process. Normal software development would include a 20% cost for testing and security but on critical or extremely critical software that might grow as high as 40% of the total cost.

    Ensure a smooth run with ongoing application support.

    Designing and developing the application is just the start. Once it is built, it must be operated from somewhere by someone (hosting), and all software needs periodic maintenance such as security updates. 

    What about hosting?

    Hosting alone could be an entirely separate article but we’ll take a quick swag at it based on what you found above. For most web applications we recommend a cloud environment for scale and redundancy. Amazon Web Services, Google Cloud Platform, Microsoft Azure to name a few. Processing cycles, storage, bandwidth, backup, disaster recovery, and other details all add to the cost. With a disclaimer on accuracy for your particular application, here are some ballparks below. 

    Micro  Small Medium Large
    < $100 / month $100-$500 / month $1,000-$5,000 / month $5,000-$100,000+ /month

    Don’t forget application management.

    Applications have an ongoing cost of ownership — all software, especially critical applications, need security updates, periodic maintenance, updates to supporting software and technology, and perhaps testing of backup and disaster recovery. To keep your application secure and performing well, these need to be performed as preventive maintenance, not as an emergency response after problems occur.

    To make sure all these happen, you will want some level of application management, whether that’s internal or through a managed service provider like Atlantic BT. Because you have a custom application your best bet in choosing a managed service provider will be a company that can both manage the hosting of your application and the ongoing application development and support. It’s very rare that you “finish” developing your application. Normally, you continue to evolve and improve your application over the course of the time it is in production. Choosing a managed service provider that has a continuous DevOps chain from development through hosting will ensure efficient, continuous operation.

    The costs of managed services around a custom application could range from 5%-20% depending on how well it was built originally and how many features and requests you want to continue to add as the application is used. 

    Are the numbers starting to make sense?

    This web application cost calculator will help guide you in the right direction for a ballpark estimate. More importantly, it tells you how to approach estimation in general for software development and lifecycle maintenance. If you want a more refined estimate, contact us for a free consultation. We can help you with everything from a quick idea over a phone call to structured requirements-gathering and a detailed estimate process.Â