ASP.NET Web API documentation using Swagger – Introduction

Providing always up-to-date and exhaustive documentation for your WEB API could be quite a challenging task.
Swagger and Swashbuckle did a great job to provide uniform documentation for any kind of API.
Let’s look into this using simple demo discount API example.

Setup ASP.NET WEB API project

First, create empty ASP.NET Web API project.
Add new controller – DiscountController inside Controllers folder.

using System;
using System.Web.Http;
using SwaggerDemo.Models;

namespace SwaggerDemo.Controllers
{
    public class DiscountController : ApiController
    {
        [Route("discounts")]
        public IHttpActionResult Post(DiscountModel model)
        {
            model.Id = 2017;
            return Created("", model);
        }

        [Route("discounts/{id}")]
        public IHttpActionResult Get(int id)
        {
            return Ok(new DiscountModel
            {
                Id = id,
                StartDate = new DateTime(2017, 10, 31),
                EndDate = new DateTime(2019, 10, 31),
                Type = "PercentOff",
                Value = 35
            });
        }
    }
}


DiscountModel class:

using System;

namespace SwaggerDemo.Models
{
    public class DiscountModel
    {
        public int Id { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }
        public string Type { get; set; }
        public decimal Value { get; set; }
    }
}

Now if we run F5 or Debug in Visual Studio, our new API is accessible at http://localhost:50217/discounts/25 (50217 is port number, could be different on your machine)

Add Swashbuckle to the project

Swashbukle page says: Seamlessly adds a swagger to WebApi projects! And it works in that way, all you need is to install it from Nuget and you are ready to start.
Now rerun application, you could now access SwaggerUI page by http://localhost:50217/swagger/ui/index

Add more documentation

Let’s look into what Swashbuckle generated by default. First look at model:

Questions that immediately appear if want to start using API:

  1. What is correct format for dates?
  2. What are possible options for field ‘Type’
  3. How much decimal point is supported for  Value field?
  4. What fields are really optional?

Let’s try to answer all those questions by providing XML comments for model properties.

    public class DiscountModel
    {
        /// <summary>
        /// Discount unique Id, auto-generated
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// Date-time string in <a href="https://en.wikipedia.org/wiki/ISO_8601#UTC">ISO 8601 format</a>.
        /// Date-time without time-zone is treated as UTC.
        /// </summary>
        [Required]
        public DateTime StartDate { get; set; }

        /// <summary>
        /// Date-time string in <a href="https://en.wikipedia.org/wiki/ISO_8601#UTC">ISO 8601 format</a>.
        /// Date-time without time-zone is treated as UTC.
        /// </summary>
        [Required]
        public DateTime EndDate { get; set; }

        /// <summary>
        /// Possible values are: PercentOff and MoneyOff
        /// </summary>
        [Required]
        public string Type { get; set; }

        /// <summary>
        /// Max number of decimal places is 2. E.g. provided 35.355 will be truncated to 35.35.
        /// </summary>
        [Required]
        public decimal Value { get; set; }
    }
  1. Enable XML comments in SwaggerConfig
    Uncomment and edit line:

    c.IncludeXmlComments(System.Web.Hosting.HostingEnvironment.MapPath("~/bin/SwaggerDemo.xml")); 
  2. Enable XML documentation output during project build
    Go Project Properties => Build section => Check XML documentation file checkbox.

Let’s build and run the project, now model looks much nicer providing guidance on how to use discount model.

Summary:

Enabled Swagger documentation for Web API project.
Added model property XML comments to provide information about expected input options and its format.
Used DataAnnotations to document required model properties.

Posted in Documentation, WEB API | Tagged , | Leave a comment

AutoFixture > Using [Frozen] attribute on test method parameter

[Frozen] attribute is used to freeze instances of objects. It is applied on test method parameters.
We will consider simple examples with string comparison test.

Without [Frozen] attribute

using Ploeh.AutoFixture.Xunit2;
using Xunit;

[Theory, InlineAutoData]
public void No_Frozen_Attribute_Generates_Random_Strings(
	string one,
	string two)
{
	Assert.Equal(one, two);
}

Result: Failed

Using [Frozen] attribute

Applying [Frozen] on the first parameter of type string, will return the same values for all subsequent parameters.

[Theory, InlineAutoData]
public void Frozen_On_Parameter_Name_Freeze_Object_Instance(
   [Frozen]string one,
	string two)
{
	Assert.Equal(one, two);
}

Result: Passed

Using [Frozen] attribute – Order is important!

Applying [Frozen] attribute on the second parameter will generate two random strings.
But if we have third parameter of type ‘string’, then it will have the same value as ‘two’.

[Theory, InlineAutoData]
public void Frozen_On_Parameter_Name_Order_Is_Important(
	string one,
	[Frozen]string two)
{
	Assert.Equal(one, two);
}

Result: Failed

Posted in Unit test | Tagged , | Leave a comment

AutoFixture > Customize objects creation with ICustomization interface

In this post we will look at AutoFixture basic customization features starting with ICustomization interface.

We will use following DateRange class as demonstration example.

    public class DateRange
    {
        public DateTime Start { get; private set; }
        public DateTime Finish { get; private set; }

        public DateRange(DateTime start, DateTime finish)
        {
            if (start > finish)
            {
                throw new ArgumentException("Finish date must be less than or equal to Start date");
            }

            Start = start;
            Finish = finish;
        }
    }

If we write test method using DateRange as parameter:

using Ploeh.AutoFixture;
using Ploeh.AutoFixture.Xunit2;
using Xunit;

public class DateRangeTests
    {
        [Theory, AutoData]
        public void ShowCaseTest(DateRange sut)
        {
            //skip the body to focus at the DateRange object creation
        }
    }

Test will sometimes fail with “System.ArgumentExceptionFinish date must be less than or equal to Start date”. Because by default AutoFixture library will just pass two random DateTime as constructor parameter and the validation logic inside constructor is not considered.

Let’s fix it by implementing ICustomization interface to create valid DateRange object.

 public class CustomAutoDataAttribute : AutoDataAttribute
    {
        public CustomAutoDataAttribute()
            : base(new Fixture()
            .Customize(new ValidDateRangeCustomization()))
        { }
    }

    public class ValidDateRangeCustomization : ICustomization
    {
        public void Customize(IFixture fixture)
        {
            fixture.Register(() =>
            {
                var start = fixture.Create<DateTime>();
                return new DateRange(start, start.AddDays(1));
            });
        }
    }

The last step is to to use CustomAutoData in the test instead of default AutoData.

    [Theory, CustomAutoData]
    public void DoSomeTest(DateRange sut)
    {

    }
Posted in programming, Unit test | Tagged , | Leave a comment

Using discriminated unions to fix Liskov substitution principle violation

As an example of LSP violation, I will consider e-commerce payment system design. One needs to develop generic mechanism for multiple payment service providers (PSP) that are using on checkout step.

From the requirements there are different kinds of PSP in terms of integration. There are PSP that require customer to be redirected to PSP portal page, where customer needs to enter payment information, e.g. credit card. On the other hand, there are PSP that provide possibility to integrate through the API where the response is synchronous, e.g. direct payments.

Knowing that, we could start to design simple interface with two methods for different type of payments, and trying to provide several implementations.


    public interface IPaymentProvider
    {
        PaymentFormDetails GetPaymentFormDetails(Order order);
        PaymentResponse MakeDirectPayment(Order order);
    }

    public class PayPalDirectPaymentProvider : IPaymentProvider
    {
        public PaymentFormDetails GetPaymentFormDetails(Order order)
        {
            throw new NotSupportedException("Not supported for Direct payments. Used only for 3D secure payments.");
        }

        public PaymentResponse MakeDirectPayment(Order order)
        {
           //do some real job here, e.g. call real services etc
            return new PaymentResponse()
            {
                TransactionId = Guid.NewGuid().ToString()
            };
        }
    }

    public class PayPalStandartPaymentProvider : IPaymentProvider
    {
        public PaymentFormDetails GetPaymentFormDetails(Order order)
        {
            return new PaymentFormDetails();
        }

        public PaymentResponse MakeDirectPayment(Order order)
        {
            throw new NotSupportedException("Direct payments are not supported by PayPal direct.");
        }
    }

    public class PaymentResponse
    {
        public string TransactionId { get; set; }
    }

    public class Order
    {
        public decimal Amount { get; set; } 
        public string OrderNumber { get; set; }
    }

    public class PaymentFormDetails
    {
        public string PaymentGatewayUrl { get; set; }
        public string OrderNumber { get; set; }
        public decimal Amount { get; set; }
    }

Unfortunately there is no way for specific payment provider to implement both of methods, so we have to throw NotSupportedException. That is clearly indicates LSP violation.

As we try to adhere to SOLID principles, let’s try to fix the violation.

LSP violation fix#1 – NotSupportedException

First attempt could be to introduce marker interface, it could greatly simplified interface and implementations themselves,
But now calling side should perform downcasting from interface to its implementation in order to correctly interpret the result.

 public interface IPaymentProvider
    {
        IPaymentRequestProcessingResult ProcessPaymentRequest(Order order);
    }

    public interface IPaymentRequestProcessingResult
    {
    }

    public class PaymentResponse : IPaymentRequestProcessingResult
    {
        public string TransactionId { get; set; }
    }

    public class PaymentFormDetails : IPaymentRequestProcessingResult
    {
        public string PaymentGatewayUrl { get; set; }
        public string OrderNumber { get; set; }
        public decimal Amount { get; set; }
    }

    public class PayPalDirectPaymentProvider : IPaymentProvider
    {
        public IPaymentRequestProcessingResult ProcessPaymentRequest(Order order)
        {
            //do some real job here, e.g. call real services etc
            return new PaymentResponse()
            {
                TransactionId = Guid.NewGuid().ToString()
            };
        }
    }

    public class PayPalStandartPaymentProvider : IPaymentProvider
    {
        public IPaymentRequestProcessingResult ProcessPaymentRequest(Order order)
        {
            return new PaymentFormDetails()
            {
                Amount = order.Amount,
                OrderNumber = order.OrderNumber,
                PaymentGatewayUrl = "https://www.paypal.com"
            };
        }
    }

Remove LSP violation#2 – Downcasting and type checking. Introduce discriminated union

Discriminated union is terms came from functional langauges, particularly from F#. Base on Microsoft documentation

Discriminated unions provide support for values that can be one of a number of named cases, possibly each with different values and types. Discriminated unions are useful for heterogeneous data;

https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/discriminated-unions

Discriminated unions and not supported out of the box in C#, but there are several ready to use implementations over the Internet. I used implementation from here http://pastebin.com/EEdvVh2R

public sealed class Union2<A, B>
    {
        readonly A Item1;
        readonly B Item2;
        int tag;

        public Union2(A item) { Item1 = item; tag = 0; }
        public Union2(B item) { Item2 = item; tag = 1; }

        public T Match<T>(Func<A, T> f, Func<B, T> g)
        {
            switch (tag)
            {
                case 0: return f(Item1);
                case 1: return g(Item2);
                default: throw new Exception("Unrecognized tag value: " + tag);
            }
        }
    }

Than we will remove from

  public interface IPaymentProvider
    {
        PaymentRequestProcessingResult ProcessPaymentRequest(Order order);
    }

    public class PaymentRequestProcessingResult: Union2<PaymentResponse, PaymentFormDetails>
    {
        public PaymentRequestProcessingResult(PaymentResponse item) : base(item)
        {
        }

        public PaymentRequestProcessingResult(PaymentFormDetails item) : base(item)
        {
        }
    }

And implementations now:

 public class PayPalDirectPaymentProvider : IPaymentProvider
    {
        public PaymentRequestProcessingResult ProcessPaymentRequest(Order order)
        {
            //do some real job here, e.g. call real services etc
            return new PaymentRequestProcessingResult(
                new PaymentResponse()
                {
                    TransactionId = Guid.NewGuid().ToString()
                });
        }
    }

    public class PayPalStandartPaymentProvider : IPaymentProvider
    {
        public PaymentRequestProcessingResult ProcessPaymentRequest(Order order)
        {
            return new PaymentRequestProcessingResult(new PaymentFormDetails()
            {
                Amount = order.Amount,
                OrderNumber = order.OrderNumber,
                PaymentGatewayUrl = "https://www.paypal.com"
            });
        }
    }

And finally usage,

public static void Main()
        {
            var order = new Order
            {
                Amount = 20m,
                OrderNumber = "00001"
            };

            Console.WriteLine("Select payment provider (1 - PayPal Direct, 2 - PayPal standart):");
            var pl = int.Parse(Console.ReadLine());
            var paymentProvider = GetPaymentProvider(pl);

            var res = paymentProvider.ProcessPaymentRequest(order);

            Console.WriteLine(res.Match(
                r => "Direct payment succeed. Transaction ID:" + r.TransactionId,
                fd => "Standart payment providers. Redirecting to PSP. Paymew gateway url:" + fd.PaymentGatewayUrl));

            Console.Read();
        }

ProcessPaymentRequest method results are clearly defined and allow to use them in type-safe manner.

Review

Let’s review what we achieved so far:

  • Removed throwing NotSupportedException
  • Eliminate downcasting to specific class types
  • Enable type-safe way of working with possible payment processing results
Posted in object-oriented-principles, software-patterns | Leave a comment

FAKE.IIS Add application to existing IIS site

Recently I had a task to change IIS application path in existing IIS site.
That was repetitive operation so I decided to write script for it.

I recently began to study F# and function programming so decided to try FAKE.
There is also cool explanation of FAKE here: http://blog.tamizhvendan.in/blog/2015/01/06/step-4-build-automation-using-fake/.

I have easily find IIS() function, that allows to get all the things ready at once: setup site/application pool/applications.
IIS() works in way that it will not create new site or application pool, if the same already exists.
But it will always add new version of site bindings even if the same is already exists. It makes IIS site stopped and there extra binding are to be taken care manually.

That said, I created interactive script, *.fsx file.
It is “hardcoded” and not error safe, but contains some parts, that I spent time struggling with, like figuring out where to take instance of ServerManager to create application etc.


#r @"packages/FAKE/tools/Fake.IIS.dll"
#r @"packages/FAKE/tools/FakeLib.dll"
#r @"packages/FAKE/tools/Microsoft.Web.Administration.dll"

open System
open System.Security.Principal
open Microsoft.Web
open Microsoft.Web.Administration
open Fake
open Fake.IISHelper

let siteName = "site"
let vdir = "/dir"
let path = @"C:\IIS\site\dir"

let addNewApp vdir path = 
    use mgr = new ServerManager()
    let site = mgr.Sites.[siteName]
    let app = Application vdir path site mgr
    commit mgr
Posted in F# | Tagged , | Leave a comment

Tools and libraries to consider when writing autotests

Below is a summary of tools/libraries I have used to build large maintainable suite of auto tests on large web project.

Test Framework

XUnit

xUnit.net is a developer testing framework, built to support Test Driven Development, with a design goal of extreme simplicity and alignment with framework features.

Test setup

AutoFixture

AutoFixture makes it easier for developers to do Test-Driven Development by automating non-relevant Test Fixture Setup, allowing the Test Developer to focus on the essentials of each test case. (copied from nuget package description)

I could not stress enough how useful the library is. It allows to greatly decrease the lines of code for your test suits and make tests more readable.

AutoFixture.XUnit2

By leveraging the data theory feature of xUnit.net, this extension turns AutoFixture into a declarative framework for writing unit tests. In many ways it becomes a unit testing DSL (Domain Specific Language).

Test assert

FluentAssertions

A very extensive set of extension methods that allow you to more naturally specify the expected outcome of a TDD or BDD-style unit test. (copied from nuget package description)

It providesa a lot more possibilities to assert the test outcome than standard test frameworks do.

ApprovalTests

A picture’s worth a 1000 tests. Unit testing asserts can be difficult to use. Approval tests simplify this by taking a snapshot of the results, and confirming that they have not changed.

Posted in Unit test | Tagged | Leave a comment

How to identify process ID in PerfMon

Last time I need to troubleshoot memory leak in IIS process hosted on productions server I decided to start with PerfMon and got stuck on Add Counters screen, where I saw seventeen w3wp (IIS process name) processes up to w3wp#17.

Here for the demo I used two instances of the same console application. It is enough to get the idea.

Add Counters

It occurs that there are some advice how to identify PID of the process, most of them about changing registry settings, and it  does not always help.

Others suggest to use third-party tools to match PerfMon process identification with real PID.

I used another solution. Add another performance counter, like on the screen below.

Add Counters 2016-03-22 22.59.16

Now I have possibility to identify that process I was interested in was #1.

Performance Monitor 2016-03-22 23.03.39

Happy using PerfMon. It is amazing!

Posted in SysInternals | Tagged | Leave a comment