How to pass in Uri complex objects without using custom ModelBinders or any serialization?

Do you wonder why I publish such an article?
Well, recently it happened to me to ask to a legacy information system in which I was to find information of users only with their name and their first name…
Yes yes using their name first name:).

I had to send to the WebApi a list of name/first name, the whole paginated, how did I make it?

At the beginning I had the idea to create my search model object in JSON which I would have to serialize while passing it in the URL, then, I had the idea to create an object with a string property containing the list of the names/firstnames the whole “decorated with separators” then split it in the WebAPI with a custom ModelBinder. Finally I decided I’d rather understand how to pass in the Uri more or less complex objects without using of ModelBinder or serialisation?.

Here what I did:

I tested 2 scenarios, the first with a list of “Person” and a second with a little more complex object “ListOfPersons”.
Before starting, as a reminder, I just want to remind you how we pass in a Uri a string collection.

namespace QueryStringDemo.Models
{
    public class Person
    {
        public string FirstName { get; set; }

        public string LastName { get; set; }
    }
}
namespace QueryStringDemo.Models
{
    public class ListOfPersons
    {
        public int? PageNumber { get; set; } 
        public int? PageSize { get; set; }
        public List Persons { get; set; }
    }
}
using QueryStringDemo.Models;
using System.Collections.Generic;
using System.Web.Http;

namespace QueryStringDemo.Controllers
{
    [RoutePrefix("api/demo")]
    public class DemoController : ApiController
    {
        [Route("simplelist")]
        [HttpGet]
        public IHttpActionResult Get([FromUri]List strings)
        {
            return Ok();
        }

        [Route("simplelistOfpersons")]
        [HttpGet]
        public IHttpActionResult Get([FromUri]List listOfPersons)
        {
            return Ok();
        }

        [Route("complexlistOfpersons")]
        [HttpGet]
        public IHttpActionResult Get([FromUri]ListOfPersons listOfPersons)
        {
            return Ok();
        }
    }
}

1- Scenario 1, reminder, string collection :

Uri :

scenario1-url

Result in code :

scenario1-code

Note that you have to use the attribute [FromUri], it provides deserialization to the target object from a complex object that comes from the queryString.

2- Scenario 2, collection of person object :

Uri :

scenario2-url

Result in code :

scenario2-code-1

Note that the object is in fact an array, an array like this

?[index].PropertyName=Value

3- Scenario 3, a more complex collection of person object :

Uri :

scenario3-url

Result in code :

scenario3-code

Note that it works also with an array,
our object looks like this :

?PropertyName1=value&PropertyName2=value&PropertyName3[index].SubPropertyName1=value&PropertyName3[index].SubPropertyName2=value

Finally we have demystified how queryString native serialization/deserialization works, was it so complicated ? 🙂

Injection Dependency: Bring your own container in .NET Core Web API, example with Simple Injector

Introduction of Simple Injector

Simple Injector is an easy-to-use Dependency Injection (DI) library for .NET that supports .NET Core, Xamarin, Mono and Universal apps. Simple Injector is easily integrated with frameworks such as Web API, MVC, WCF, ASP.NET Core and many others. It’s easy to implement the dependency injection pattern with loosely coupled components using Simple Injector.

Why Simple Injector? It’s simple to use, free, fast, support advanced generics types, and provide powerful diagnostics services.

If you want to know more about you can check the documentation here: https://simpleinjector.readthedocs.io/en/latest/quickstart.html

Installation of Simple Injector in ASP.NET Core WebAPI

Select and Install SimpleInjector.Integration.AspNetCore.Mvc from “Manage Nuget packages” panel

or type the following command in “Package manager console”:

Install-Package SimpleInjector.Integration.AspNetCore.Mvc -Version 4.0.12

Configuration of Simple Injector in ASP.NET Core WebAPI

  • Import SimpleInjector, SimpleInjector.Lifestyles and SimpleInjector.Integration.AspNetCore.Mvc namespaces
  • Add a Container property in your class Startup.cs
  • Register your service with its appropriate Interface, Simple Injector supports concrete injection (the class without its interface), you can set Lifestyle.Scoped, Lifestyle.Singleton or Lifestyle.Transient
  • Optionnally add Verify method,  (after RegisterMvcControllers method in Configure method) it iterates registered service to check if something is not correct, will throw an exception before any execution of the program
  • Add SimpleInjectorControllerActivator that implements IControllerActivator to provide dependency injection resolution in controllers constructor
  • Then add the extension method UseSimpleInjectorAspNetRequestScoping that ASP.NET requests into Simpleinjector’s scoped lifestyle

Example:

public interface IHelloWorldService
{
   string HelloWorld();
}
public class HelloWorldService : IHelloWorldService
{
   public string HelloWorld()
   {
      return "Hello world";
   }
}
[Route("api/[controller]")]
public class HelloController : Controller
{
   private IHelloWorldService _helloService;

   public HelloController(IHelloWorldService helloService)
   {
      _helloService = helloService;
   }

   [HttpGet]
   public string Get()
   {
      return _helloService.HelloWorld();
   }
}
public class Startup
{
   private Container container = new Container();

   public Startup(IConfiguration configuration)
   {
      Configuration = configuration;
   }

   public IConfiguration Configuration { get; }

   // This method gets called by the runtime. Use this method to add services to the container.
   public void ConfigureServices(IServiceCollection services)
   {
      services.AddMvc();

      // Default lifestyle scoped + async
      // The recommendation is to use AsyncScopedLifestyle in for applications that solely consist of a Web API(or other asynchronous technologies such as ASP.NET Core)
      container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

      // Register services
      container.Register<IHelloWorldService, HelloWorldService>(Lifestyle.Scoped); // lifestyle can set here, sometimes you want to change the default lifestyle like singleton exeptionally

      // Register controllers DI resolution
      services.AddSingleton<IControllerActivator>(new SimpleInjectorControllerActivator(container));

      // Wrap AspNet requests into Simpleinjector's scoped lifestyle
      services.UseSimpleInjectorAspNetRequestScoping(container);

  }

   // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
   public void Configure(IApplicationBuilder app, IHostingEnvironment env)
   {
      if (env.IsDevelopment())
      {
         app.UseDeveloperExceptionPage();
      }

      app.UseMvc();

      container.RegisterMvcControllers(app);

      // Verify Simple Injector configuration
      container.Verify();
   }
}

 

Execution:

 

We did it! we brought our own dependency injection container 🙂

Injection Dependency: Bring your own container in .NET Core console App, example with Simple Injector

Introduction of Simple Injector

Simple Injector is an easy-to-use Dependency Injection (DI) library for .NET that supports .NET Core, Xamarin, Mono and Universal apps. Simple Injector is easily integrated with frameworks such as Web API, MVC, WCF, ASP.NET Core and many others. It’s easy to implement the dependency injection pattern with loosely coupled components using Simple Injector.

Why Simple Injector? It’s simple to use, free, fast, support advanced generics types, and provide powerful diagnostics services.

If you want to know more about you can check the documentation here: https://simpleinjector.readthedocs.io/en/latest/quickstart.html

Installation of Simple Injector in a console app

Select and Install it from “Manage Nuget packages” panel

or type the following command in “Package manager console”:

PM> Install-Package SimpleInjector -Version 4.0.12

Configuration of Simple Injector in a console app

  • Import SimpleInjector and SimpleInjector.Lifestyles namespaces
  • Add a static Container property in your class Program
  • Register your service with its appropriate Interface, Simple Injector supports concrete injection (the class without its interface)
  • Optionnally add Verify method, it iterates registered service to check if something is not correct, will throw an exception before any execution of the progam
  • Then use GetInstance method to get your service

Example :

public interface IMyService
{
   string HelloWorld();
}
public class MyService: IMyService
{
   public string HelloWorld()
   {
      return "Hello world!";
   }
}
using SimpleInjector;
using System;

namespace ConsoleAppDemoWithSimpleInjector
{
   class Program
   {
      static readonly Container container;

      static Program()
      {
         container = new Container();

         container.Register<IMyService, MyService>();

         container.Verify();
      }

      static void Main(string[] args)
      {
         var service = container.GetInstance<IMyService>();
         Console.WriteLine(service.HelloWorld());
         Console.ReadLine();
      }
   }
}

Execution:

Configuration of Simple Injector in a console app thats runs undefinitely

In the absence of any framework code, you are yourself responsible to tell Simple Injector that certain code must run in isolation. This can be done with Scoping. There are two types of scoped lifestyles that can be used. ThreadScopedLifestyle allows wrapping code that runs on a single thread in a scope, where AsyncScopedLifestyle allows wrapping a block of code that flows asynchronously (using async await).

The following example demonstrates a simple Console application that runs indefinitely, and executes a request every second. The request is wrapped in a scope:

class Program
{
   static readonly Container container;

   static Program()
   {
      container = new Container();
      container.Options.DefaultScopedLifestyle = new ThreadScopedLifestyle();

      container.Register<IMyService, MyService>();

      container.Verify();
   }

   static void Main(string[] args)
   {
      while (true)
      {
         using (ThreadScopedLifestyle.BeginScope(container))
         {
            var service = container.GetInstance<IMyService>();

            Console.WriteLine(service.HelloWorld());
         }

         Thread.Sleep(TimeSpan.FromSeconds(1));
      }
   }
}

By default the lifecycle of our service is Transient, it means that a new instance will be created each we ask an instance of our service, else you can set Singleton.

Transient lifestyle

container.Register<IMyService, MyService>(Lifestyle.Transient);

or

container.Register<IMyService, MyService>();

Singleton lifestyle

container.Register<IMyService, MyService>(Lifestyle.Singleton);

Example that display Guid of the instance:

public class MyService: IMyService
{
   private Guid _guid;

   public MyService()
   {
      _guid = Guid.NewGuid();
   }

   public string HelloWorld()
   {
      return $"Hello world! instance: {_guid}";
   }
}

Execution :

Transient lifestyle

Guid are not identicals

Singleton lifestyle

Guid are identicals

 

Simple isn’it ? 🙂