European ASP.NET 4.5 Hosting BLOG

BLOG about ASP.NET 4, ASP.NET 4.5 Hosting and Its Technology - Dedicated to European Windows Hosting Customer

European ASP.NET Core Hosting :: How to Use Dapper Asynchronously in ASP.NET Core 2.1

clock November 12, 2018 08:13 by author Scott

In this post, we're going to create a very simple ASP.NET Core 2.1 application which uses Dapper to access data. There's already a sample project worked up over on GitHub, and you might want to use that to follow along here.

Step 1: Get the NuGet Package

First things first, we need to grab the NuGet package for Dapper. In Visual Studio, you can do this by right-clicking on your project file and selecting Manage NuGet Packages and then search for the Dapper package, like so:

With that installed, let's try creating a repository.

Step 2: Creating an Employee Class and Repository

For this demo, I am not going to go over how to create a database or show a demo database with sample data; I don't have one available and it's a pain to make one. So let's assume we have a table Employee with columns for FirstName, LastName, ID, and DateOfBirth. We can make a corresponding C# class for this table, like so:

public class Employee
{
   
public int ID { get; set; }
   
public string FirstName { get; set; }
   
public string LastName { get; set; }
   
public DateTime DateOfBirth { get; set; }
}

Now we need a sample repository. Let's call it EmployeeRepository and give it an interface so we can use ASP.NET Core's Dependency Injection setup.

Here's the interface:

public interface IEmployeeRepository
{
   
Task<Employee> GetByID(int id);
   
Task<List<Employee>> GetByDateOfBirth(DateTime dateOfBirth);
}

Now we can work up a skeleton implementation of this repository. Here's what we're starting with:

public class EmployeeRepository : IEmployeeRepository
{
   
public async Task<Employee> GetByID(int id)
   
{

   
}

   
public async Task<List<Employee>> GetByDateOfBirth(DateTime dateOfBirth)
    {

We also need to update our project's Startup file to include our new repository in the services layer:

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

   
public IConfiguration Configuration { get; }

   
public void ConfigureServices(IServiceCollection services)
   
{
       
services.AddTransient<IEmployeeRepository, EmployeeRepository>();

       
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
   
}

   
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
   
{
       
//...
   
}
}

Next, we need to enable this repository to use Dapper. Before we can do that, however, we need it to be aware of what connection string we are using.

Step 3: Injecting IConfiguration

Very often in ASP.NET Core projects, Connection Strings are defined in the appSettings.json file:

{
 
"Logging": {
   
"LogLevel": {
     
"Default": "Debug",
     
"System": "Information",
     
"Microsoft": "Information"
   
}
 
},
 
"ConnectionStrings": {
   
"MyConnectionString": "MyConnectionString"
 
}
}

The problem is: how do we pass that connection string to the repository so it can create a SqlConnection object for Dapper to use.

ASP.NET Core introduces a new IConfiguration object which can be injected into other classes. That injected instance will contain a method called GetConnectionString which we can use to obtain our connection string from the appSettings.json files. So, let's inject IConfiguration like so:

public class EmployeeRepository : IEmployeeRepository
{
   
private readonly IConfiguration _config;

   
public EmployeeRepository(IConfiguration config)
   
{
       
_config = config;
    }
   

   
//Remainder of file is unchanged
}

Step 4: Creating a SqlConnection

With the injected IConfiguration now available to our repository, we can create a Dapper-enabled SqlConnection object that all of our repository's methods can utilize.

public class EmployeeRepository : IEmployeeRepository
{
   
private readonly IConfiguration _config;

   
public EmployeeRepository(IConfiguration config)
   
{
       
_config = config;
   
}

   
public IDbConnection Connection
   
{
       
get
       
{
           
return new SqlConnection(_config.GetConnectionString("MyConnectionString"));
       
}
    }
   

   
//Remainder of file is unchanged
}

Step 5: Employee by ID

Let's first create a method to return employees by their ID.

To start, let's remember that the way Dapper works is by processing raw SQL and then mapping it to an object. Because our table columns and object properties share the same names, we don't need to do any special mapping here.

Here's the implementation of our GetByID method:

public class EmployeeRepository : IEmployeeRepository
{
   
//...

   
public async Task<Employee> GetByID(int id)
   
{
       
using (IDbConnection conn = Connection)
        {

            string sQuery = "SELECT ID, FirstName, LastName, DateOfBirth FROM Employee WHERE ID = @ID";
           
conn.Open();
           
var result = await conn.QueryAsync<Employee>(sQuery, new { ID = id });
           
return result.FirstOrDefault();
       
}
   
}
}

Step 6: Employees by Date of Birth

We also need to get all employees born on a particular date. Since we are now returning a collection of employees rather than a single one, the implementation changes very slightly.

public class EmployeeRepository : IEmployeeRepository
{
    //...
   

     
public async Task<List<Employee>> GetByDateOfBirth(DateTime dateOfBirth)
   
{
       
using (IDbConnection conn = Connection)
       
{
           
string sQuery = "SELECT ID, FirstName, LastName, DateOfBirth FROM Employee WHERE DateOfBirth = @DateOfBirth";
           
conn.Open();
           
var result = await conn.QueryAsync<Employee>(sQuery, new { DateOfBirth = dateOfBirth });
           
return result.ToList();
       
}
   
}
}

Step 7: Implement the Controller

The final step is creating a controller to which our EmployeeRepository can be injected. Here it is:

[Route("api/[controller]")]
[ApiController]
public class EmployeeController : ControllerBase
{
   
private readonly IEmployeeRepository _employeeRepo;

   
public EmployeeController(IEmployeeRepository employeeRepo)
   
{
       
_employeeRepo = employeeRepo;
   
}

   
[HttpGet]
   
[Route("{id}")]
   
public async Task<ActionResult<Employee>> GetByID(int id)
   
{
       
return await _employeeRepo.GetByID(id);
   
}

   
[HttpGet]
   
[Route("dob/{dateOfBirth}")]
   
public async Task<ActionResult<List<Employee>>> GetByID(DateTime dateOfBirth)
   
{
       
return await _employeeRepo.GetByDateOfBirth(dateOfBirth);
   
}
}

Summary

That's it! We've implemented Dapper into our ASP.NET Core 2.1 application!



European ASP.NET Core Hosting :: How to Measure and Report the Response Time of ASP.NET Core

clock November 8, 2018 09:57 by author Scott

Performance is a buzzword for APIs. One of the most important and measurable parameters of the API performance is the response time. In this article, we will understand how to add code to measure the response time of an API and then return the response time data to the end client.

What is the need for this?

So, let's take a moment to think why we would ever need such a feature to measure the Response time of an API. Following are some of the points that have been the inspiration for writing code to Capture response time.

  • You need to define the SLA (Service Level Agreements) for your API with your clients. The clients need to understand how much time  the API takes to respond back. The response time data over time can help us decide on an SLA for our API.
  • Management is interested in reports as to how fast or slow the application is. You need to have data to corroborate your claims. It is worth it to have reports on the performance of the application and to share it with Stakeholders.
  • The client needs to have the information of the Response time of the API so that they can track how much time is spent on the client and the Server.

You might also have encountered similar requests in your project and it is worthwhile looking at an approach to capture the response time for the API.

Where to add the code?

Let's explore a couple of approaches to capture the response time of our API focusing mostly on capturing the time spent in our API. Our objective is to calculate the time elapsed in milliseconds from the time the request is received by the Asp.net core runtime to the time the response is processed and sent back from the Server.

What factors are we ignoring?

It's important to understand that this discussion doesn't include the time spent in N/W, Time spent in IIS and Application Pool Startup. If the Application Pool wasn't up and running, then the first request can affect the overall response time of the API. There is an Application Initialization Module which we can make use of but that is out of scope for this article.

First Attempt

One very naive approach to capturing the response time of an API would be to add code to every API method at the start and end and then measure the delta to calculate the response time as shown 

// GET api/values/5   
[HttpGet]  
public IActionResult Get() {  
    // Start the watch   
    var watch = new Stopwatch();  
    watch.Start();  
    // Your actual Business logic   
    // End the watch  
    watch.Stop();  
    var responseTimeForCompleteRequest = watch.ElapsedMilliseconds;  
} 

This code should be able to calculate the time spent in an operation. But this doesn't seem to be the right approach for the following reasons.

If an API has a lot of operations, then we need to add this code to multiple places which are not good for maintainability.

This code measures the time spent in the method only, it doesn't measure the time spent on other activities like middleware, filters, Controller selection, action method selection, Model binding etc.

Second Attempt

Let's try to improve the above code by centralizing the code in one place so that it is easier to maintain. We need to execute the response time calculation code before and after a method is getting executed. If you have worked with earlier versions of Asp.net Web API, you would be familiar with concepts of Filter. Filters allow you to run code before or after specific stages in the request processing pipeline.

We will implement a filter for calculating the Response time as shown below. We will create a Filter and use the OnActionExecuting to start the timer and then stop the timer in method OnActionExecuted, thus calculating the response time of the API.

public class ResponseTimeActionFilter: IActionFilter { 
    private const string ResponseTimeKey = "ResponseTimeKey"; 
    public void OnActionExecuting(ActionExecutingContext context) { 
        // Start the timer  
        context.HttpContext.Items[ResponseTimeKey] = Stopwatch.StartNew(); 
    } 
    public void OnActionExecuted(ActionExecutedContext context) { 
        Stopwatch stopwatch = (Stopwatch) context.HttpContext.Items[ResponseTimeKey]; 
        // Calculate the time elapsed  
        var timeElapsed = stopwatch.Elapsed; 
    } 
}  

This code is not a reliable technique for calculating the response time as it doesn't address the issue of calculating the time spent in execution of middleware, controller selection, action method selection, model binding etc. The filter pipeline runs after the MVC selects the action to execute. So, it effectively doesn't instrument the time spent in the Other Asp.net pipeline. 

Third Attempt

We will use the Asp.net Core Middleware to Calculate the Response time of the API.

So, what is Middleware?

Basically, Middleware are software components which handle the Request/Response. Middleware is assembled into an application pipeline and serves in the incoming request. Each component does the following operations.

  • Chooses whether to pass the request to the next component in the pipeline. 
  • Can perform work before and after the next component in the pipeline is invoked.

If you have worked with HTTPModules or HTTPHandlers in ASP.NET, then you can think of Middleware as a replacement in ASP.NET Core. Some of the examples of middleware are -

  • MVC Middleware
  • Authentication
  • Static File Serving
  • Caching
  • CORS

 

 

We want to add code to start the timer once the request enters the ASP.NET Core pipeline and stop the timer once the response is processed by the Pipeline. Custom Middleware at the start of the request pipeline seems to be the best approach for getting the access to the request as early as possible and access until the last step is executed in the pipeline.

We will build a Response Time Middleware which we will add as the first Middleware to the request Pipeline so that we can start the timer as soon the request enters the Asp.net core pipeline.

What to do with the Response time data?

Once we capture the response time data we can process data in the following ways.

  1. Add the Response time data to a Reporting database or an analytics solution.
  2. Write the Response time data to a log file.
  3. Pass the response time data to a message queue which can further be processed by another application for reporting and analytics.
  4. Send the Response time information to the client applications consuming our Rest API using the Response headers.
  5. There may be other useful ways of using the response time data. Please leave a comment and tell me how you process the response time data in your application.

Let's write the code

We will write the code considering the following points.

  • Calculating the response time data for the API
  • Reporting the data back to client applications by passing the data in the Response headers.

Full code snippet for the ResponseTimeMiddleware is shown below.

public class ResponseTimeMiddleware { 
    // Name of the Response Header, Custom Headers starts with "X-"
 
    private const string RESPONSE_HEADER_RESPONSE_TIME = "X-Response-Time-ms";
 
    // Handle to the next Middleware in the pipeline
 
    private readonly RequestDelegate _next;
 
    public ResponseTimeMiddleware(RequestDelegate next) {
 
        _next = next;
 
    }
 
    public Task InvokeAsync(HttpContext context) {
 
        // Start the Timer using Stopwatch
 
        var watch = new Stopwatch();
 
        watch.Start();
 
        context.Response.OnStarting(() => {
 
            // Stop the timer information and calculate the time
  
            watch.Stop();
 
            var responseTimeForCompleteRequest = watch.ElapsedMilliseconds;
 
            // Add the Response time information in the Response headers.
  
            context.Response.Headers[RESPONSE_HEADER_RESPONSE_TIME] = responseTimeForCompleteRequest.ToString();
 
            return Task.CompletedTask;
 
        });
 
        // Call the next delegate/middleware in the pipeline
  
        return this._next(context);
 
    }
 
}

Explanation of the code

The interesting part happens in the InvokeAsync method, We use Stopwatch class to start the stopwatch once the requests enter into the first middleware of the request and then stop the stopwatch once the request has been processed and the response is ready to be sent back to the client. OnStarting method provides an opportunity to write a custom code to add a delegate to be invoked just before response headers will be sent to the client.

Lastly, we add the Response time information in a Custom Header. We use the X-Response-Time-msheader as a Response Header. As a convention, the Custom Header starts with an X.

Conclusion

In this article, we understood how to leverage ASP.NET middleware to manage cross-cutting concerns like measuring the response time of the APIs. There are various other useful use cases of using middleware which can help to reuse code and improve the maintainability of the application.

/p>



European ASP.NET Core Hosting - HostForLIFE.eu :: File logging on ASP.NET Core

clock March 8, 2017 10:13 by author Scott

ASP.NET Core introduces new framework level logging system. Although it is feature-rich it is not complex to use and it provides decent abstractions that fit well with the architecture of most web applications. This blog post shows how to set up and use Serilog file logging using framework-level dependency injection.

Configuring logging

Logging is configured in ConfigureServices() method of Startup class. ASP.NET Core comes with console and debug loggers. For other logging targets like file system, log servers etc third-party loggers must be used. This blog post uses Serilog file logger.

"dependencies": {
 
// ...
  "Serilog.Extensions.Logging.File": "1.0.0"
},

Project has now reference to Serilog file logger. Let’s introduce it to ASP.NET Core logging system. AddFile(string path) is the extension method that adds Serilog file logger to logger factory loggers collection. Notice that there can be multiple loggers active at same time.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();
    loggerFactory.AddFile("Logs/ts-{Date}.txt");
 
    // ...
}

Serilog will write log files to Logs folder of web application. File names are like ts-20170108.txt.

Injecting logger factory

Loggers are not injected to other classes. It’s possible to inject logger factory and let it create new logger. If it sounds weird for you then just check internal loggers collection of logger factory to see that also other classes that need logger have their own instances. The code below shows how to get logger to controller through framework level dependency injection.

public class DummyController : Controller
{
    private ILogger _logger;
 
    public DummyController(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger(typeof(DummyController));
    }
 
    // ...
}

Why we have to inject logger factory and not single instance of ILogger? Reason is simple – application may use multiple loggers like shown above. This is the fact we don’t want to know in parts of application where logging is done. It’s external detail that si not related to code that uses logging.

Logging

Logging is done using extension methods for ILogger interface. All classic methods one can expect are there:

  • LogDebug()
  • LogInformation()
  • LogWarning()
  • LogError()
  • LogCritical()

Now let’s write something to log.

public class DummyController : Controller
{
    private ILogger _logger;
 
    public DummyController(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger(typeof(DummyController));
    }
 
    public void Index()
    {
        _logger.LogInformation("Hello from dummy controller!");
    }
}

Making request to Dummy controller ends up with log message added to debug window and log file. The following image shows log message in output window.

And here is the same log message in log file.



European ASP.NET Core Hosting - HostForLIFE.eu :: How to Find and Use ASP.NET Core Session

clock February 24, 2017 06:41 by author Scott

I'm building a tutorial (hopefully soon to be a post) and in that tutorial I needed to use Session for some quick-and-dirty data storage. Unfortunately when I tried to use Session in my default project, it was nowhere to be found, and I was sent down a small rabbit hole trying to find it. This post will walk through a reminder of what Session is, where to find it in ASP.NET Core 1.0, an overview of the new extension methods available, and building our own custom extension method. Let's get started!

What is Session?

If you're just starting to develop in ASP.NET, you may not have encountered Session before. Session is a serialized collection of objects that are related to the current user's session. The values are usually stored on the local server memory, but there are alternate architectures where the values can be stored in a SQL database or other distributed storage solutions, especially when your servers are part of a server farm.

You can store any data you like in Session, however any data you store will only be available to the current user as long as the session is active. This means that if that user logs out, the Session data is lost; if you need to keep this data you have to find another way to store it.

Finding the Session

ASP.NET Core 1.0 has been written from the ground up to be a modular, choose-what-you-need framework. What this means is that you must explicitly include any packages you want to use in your project.

This allows us developers to maintain tight control over what functionality our ASP.NET Core projects actually need, and exclude anything that is not necessary.

In our case, Session is considered to be one of these "additional" packages. In order to include that package we need to add a reference to Microsoft.AspNet.Session in the project.json file. If we wanted to use memory as our caching backend, we would also include Microsoft.Extensions.Caching.Memory.

Once we've got the package included in our project, we need to make it available to the Services layer by modifying the ConfigureServices()method in the Startup file, like so:

public void ConfigureServices(IServiceCollection services) 
{
    ...
    services.AddMemoryCache();
    services.AddSession(options =>
    {
        options.IdleTimeout = TimeSpan.FromMinutes(60);
        options.CookieName = ".MyCoreApp";
    });
    ...
}

With all of these steps completed, you can now use Session in your projects just like in any other ASP.NET application. If you wanted to use a different cache backend (rather than memory) you could grab a different NuGet package like Redis or SqlServer. Don't forget to check NuGet if you can't find the functionality you need; it is probably there and you just need to download it.

How to Use Session

ASP.NET Core 1.0 has introduced some new extension methods that we can use for accessing and storing Session values. The odd thing is that these extensions are not in Microsoft.AspNet.Session; rather, they are in Microsoft.AspNet.Http, and so we will need to add that package.

Once we've got that package included, we can start using the extension methods:

[HttpGet]
public IActionResult Index() 
{
    var userID = Context.Session.GetInt("UserID");
    var userName = Context.Session.GetString("UserName");
    return View();
}

[HttpGet]
public IActionResult Default() 
{
    Context.Session.SetInt("UserID", 5);
    Context.Session.SetString("UserName", "John Smith");
    return View();
}

The new extension methods are:

  • Get: Returns a byte array for the specified Session object.
  • GetInt: Returns an integer value for the specified Session object.
  • GetString: Returns a string value for the specified Session object.
  • Set: Sets a byte array for the specified Session object.
  • SetInt: Sets an integer value for the specified Session object.
  • SetString: Sets a string value for the specified Session object.

Why do only these extensions exist, and not GetDouble, GetDateTime, etc? I'm really not sure. If I had to guess I'd say it is to ensure that the values are serializable, but don't quote me on that. If anybody knows the real reason, I'd love to hear it!

Creating Extension Methods

I'm not completely satisfied with these extensions; they don't have enough functionality for my tastes, and so I'm gonna build some more. Specifically, I want to build extensions that will store a DateTime in session and retrieve it.

Here's the method signatures for these extensions:

public static DateTime? GetDateTime(this ISessionCollection collection, string key) 
{

}

public static void SetDateTime(this ISessionCollection collection, string key, DateTime value) 
{

}

The ISessionCollection interface is exactly what it sounds like: a collection of items stored in Session.

Let's tackle the SetDateTime() method first. DateTimes are weird because they are not inherently serializable, but they can be converted to a serializable type: long. So, we must convert the given DateTime value to a long before it can be stored.

public static void SetDateTime(this ISessionCollection collection, string key, DateTime value) 
{
    collection.Set(key, BitConverter.GetBytes(value.Ticks));
}

The BitConverter class allows us to convert byte arrays into other types easily.

Now we can tackle the GetDateTime() method. There are two things we need to keep in mind when building this extension. First, it is entirely possible that there will be no value in Session for the specified key; if this happens, we should return null. Second, we are storing the DateTime as a long, and therefore we need to serialize it back into a DateTime type; luckily the DateTime constructor makes this really easy. The final code for the method looks like this:

public static DateTime? GetDateTime(this ISessionCollection collection, string key) 
{
    var data = collection.Get(key);
    if(data == null)
    {
        return null;
    }

    long dateInt = BitConverter.ToInt64(data, 0);
    return new DateTime(dateInt);
}

Now we can use these extensions in addition to the ones already defined.

Now we've seen Session in action, including what package to use from NuGet, what extension methods are available, and even how to build our own extension method. Let me know if this helped you out in the comments!

Happy Coding!



European ASP.NET Core Hosting - HostForLIFE.eu :: Customising model-binding conventions in ASP.NET Core

clock February 21, 2017 08:04 by author Scott

A pattern I use when building Web APIs is to create commands to represent an API operation and models to represent resources or results. We share these "common" objects with our .NET client so we can be sure we're using the same parameters names/types.

Here's an excerpt from Fabrik's API for creating a project:

public HttpResponseMessage Post(int siteId, AddProjectCommand command)
{
    var project = new CMS.Domain.Project(
        session.GetSiteId(siteId),
        command.Title,
        command.Slug,
        command.Summary,
        command.ContentType,
        command.Content,
        command.Template,
        command.Tags,
        command.Published,
        command.Private);

    session.Store(project);

    var model = CreateProjectModel(project);
    var link = Url.Link(RouteNames.DefaultRoute, new { controller = "projects", siteId = siteId, id = project.Id.ToIntId() });

    return Created(model, new Uri(link));
}

We also use commands for GET operations that have multiple parameters such as search endpoints. So instead of:

public IActionResult GetProjects(string searchTerm = null, int page = 1, int pageSize = 10)
{

}

We have a GetProjectsCommand:

public class GetProjectsCommand
{
    public string SearchTerm { get; set; }
    [MinValue(1, ErrorMessage = "Page must be greater than 0.")]
    public int Page { get; set; } = 1;
    public int PageSize { get; set; } = 20;
}

This provides a single place to encapsulate our default values and validation rules, keeping our controllers nice and lean.

Model-binding in ASP.NET Core MVC

To bind complex types to query strings in ASP.NET Web API we had to change the parameter binding rules. This is because the default was to bind complex types from the HTTP Request body.

When implementing the above pattern in ASP.NET Core I was pleasantly surprised to see that the following worked out of the box:

// GET: api/values
[HttpGet]
public IEnumerable<string> Get(GetValuesCommand command)
{

}

I thought that perhaps the framework detected that this was a HTTP GET request and therefore bound the parameter values from the query string instead.

Actually this is not the case - in ASP.NET Core, complex types are not bound from the request body by default. Instead you have to opt-in to body-based binding with the FromBodyAttribute:

// POST api/values
[HttpPost]
public void Post([FromBody]AddValueCommand command)
{
}

This seems an odd default given that (in my experience) binding complex types from the request body is far more common.

In any case, we can customise the default model-binding behaviour by providing a convention:

public class CommandParameterBindingConvention : IActionModelConvention
{
    public void Apply(ActionModel action)
    {
        if (action == null)
        {
            throw new ArgumentNullException(nameof(action));
        }

        foreach (var parameter in action.Parameters)
        {
            if (typeof(ICommand).IsAssignableFrom((parameter.ParameterInfo.ParameterType)))
            {
                parameter.BindingInfo = parameter.BindingInfo ?? new BindingInfo();
                parameter.BindingInfo.BindingSource = BindingSource.Body;
            }
        }
    }
}

Which is registered like so:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        options.Conventions.Add(new CommandParameterBindingConvention());
    });
}

This convention checks to see if the parameter type implements ICommand (a marker interface I created) and if so, instructs the framework to bind the values for this parameter from the request body.

All I have to do then is update my command with this interface:

public class AddValueCommand : ICommand
{
    public string Value { get; set; }
}

Then I can drop the unnecessary [FromBody] attribute:

// POST api/values
[HttpPost]
public void Post(AddValueCommand command)
{
}

 



European ASP.NET Core Hosting - HostForLIFE.eu :: How to Setup Webpack in ASP.NET Core

clock February 10, 2017 11:11 by author Scott

Webpack is a great tool for bundling the client side assets in your web application. In this post we'll briefly discuss why you should create bundles and see how Webpack can automate that for us in ASP.NET Core.

Why should I bundle

When building web applications, regardless of the server side framework, you'll need to get your client side resources over to the browser. You may have dozens of JavaScript and CSS files in your project but having to reference each of them individually in your HTML markup is just not ideal for production deployments.

Each browser only allows so many concurrent requests per hostname. BrowserScope has some data on this that you can view on their site. If your web application makes more than the allowed number of simultaneous requests then the additional requests will end up being queued. This leads to longer load times and a not so smooth experience for your users; especially on mobile devices.

It would be much better to group resources into bundles so that the browser would have fewer files to download and thus fewer requests to make. This will help in keeping bandwidth usage low and even with battery life on your users' devices.

What is Webpack?

Webpack is a module bundler for the static assets in your web application. Essentially, you point Webpack at the main entry point(s) of your code then it will determine the dependencies, run transformations and create bundles that you can provide to your browser. What's even better is that in addition to JavaScript Webpack can also handle CSS, LESS, TypeScript, CoffeeScript, images, web fonts and more.

Setting up

We're going to start by setting up a new ASP.NET Core project using the dotnet cli tooling. If you don't have tooling installed, you can find can setup files and instructions here. If you're not a Windows user, the tooling works on Windows, OSX and Linux so no need to worry.

Let's get started by opening a terminal and creating an empty directory. Now, we'll generate a new ASP.NET Core project by running the following command:

dotnet new -t web 

Currently, the generated project includes .bowerrc and bower.json files. You can delete these since we'll be using NPM to install packages. If you don't have NodeJS installed on your system, make sure you do so before continuing.

The next thing we'll do is create a folder called Scripts in the root of your project. You'll find out why later on. Also add an empty webpack.config.js to the root of your project. As you might have guessed, this is the file we'll use to configure Webpack. Your project layout should look something like this.

Configuring Webpack

Before we start configuring Webpack, let's check out where our assets actually are. ASP.NET Core places all the files destined for the browser inside of the wwwroot folder by default. If you take a peep inside that folder, you'll see sub folders for your your JavaScript, CSS and image files. Note, the names of these sub folders aren't important. Feel free to rename them if you wish.

Personally, I prefer to reserve the wwwroot folder for the bundles that I want to provide to the browser. What we'll do is use the Scripts directory that was created earlier for the working files that will get included in the bundles.

Let's add two pretty trivial JavaScript files to our Scripts folder.

//other.js
function func() {
    alert('loaded!');
}
module.exports = func;

//main.js
var other = require('./other');

other();

Our scripts have been written using the CommonJS module syntax. The main.js file imports other.jsand calls the exported function. Ok, simple enough. Let's take a look at webpack.config.js.

var path = require('path');

module.exports = {
    entry: {
        main: './Scripts/main'
    },
    output: {
       publicPath: "/js/",
       path: path.join(__dirname, '/wwwroot/js/'),
       filename: 'main.build.js'
    }
};

The webpack.config.js file is a CommonJS module that we'll use to setup Webpack. The sample above shows a fairly bare bones Webpack configuration. Inside of entry, we define a main module and point it to the location of main.js file since that's where our app starts. The name of the bundle can be changed to something else if you like. There's no requirement for it to be called main. Inside of output, we let Webpack know what to name the bundle file and where to place it. The publicPath property configures the relative URL that the browser will use to reference our bundles.

Alright, that's good for now. Before we generate our bundle, make sure you have Webpack installed globally on your machine. Type the following command in your terminal. You'll only have to do this once.

npm i -g webpack 

Now we're ready to create our bundle. Make sure your terminal path is at the root of your project directory. Now run

webpack 

Your terminal output should look similar to below.

In your code editor, open Views/_Layout.cshtml. Near the bottom of the file, add a script reference to our bundle.

<script src="~/js/main.build.js"></script>

The generated ASP.NET Core template adds a few scripts tags wrapped in environment tag helpers. Go ahead and remove these for now.

<environment names="Development">
        <script src="~/lib/jquery/dist/jquery.js"></script>
        <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
        <script src="~/js/site.js" asp-append-version="true"></script>
</environment>

Finally, we can run our application and see if our bundle works. Execute the following commands in the command terminal.

dotnet restore
dotnet run

Navigate to http://localhost:5000 in your browser. If everything works as expected, you should see an alert with loaded! in the browser window.

Tying the builds together

We can reduce the number of commands we have to type by leveraging the build events in project.json. Update the scripts section to include the precompile event. To see the other available events, head over to the .NET Core Tools docs.

"scripts": {
    "precompile": ["webpack"],
  },

Now running dotnet run or dotnet build will also run Webpack to generate the bundle.

Conclusion

In this post, we got a short introduction to setting up Webpack in ASP.NET Core. Webpack often gets labeled as overly complex and difficult to setup. Hopefully, this post showed you how easy it is to get started and made you a little more curious about what else it can do.



European ASP.NET Core Hosting - HostForLIFE.eu :: Cookie Authentication and Policy Based Authorization in ASP.NET Core

clock February 6, 2017 10:23 by author Scott

This is the first part of the series of articles I'll be covering about ASP.NET Core Security. We're going to start off with cookie based authentication and build our way up to configuring policy based authorization.

As part of the ASP.NET Core security, there is a new richer policy based authorization that we can use to authorize against the claims in user's possession.

Let's build an example MVC application to demonstrate the concepts. In our scenario, we'll demand users to be authenticated and have Read claim to view the home page of our application.

I am using Visual Studio 2015 Pro Edition w/Update 3 (you should also be able to use the free community edition).

1. Create a new ASP.NET Core Web Application


2. Select the Empty Template


3. We need to add the required nuget packages to configure authorization, cookie authentication, and the mvc middleware. Bring up the project.jsonfile, add the following under the dependencies section.

"Microsoft.AspNetCore.Authorization": "1.0.0"
"Microsoft.AspNetCore.Authentication.Cookies": "1.0.0"
"Microsoft.AspNetCore.Mvc": "1.0.0"


4. Once you save the project.json file, Notice Visual Studio installs the missing nuget packages automatically. Next, bring up the Startup.cs where we'll configure the middleware we just included in our project.

5. In Configure method, add the following authentication middleware configuration;

app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationScheme = "Cookies",
        LoginPath = new StringPath("/Account/Login"),
        AccessDeniedPath = new StringPath("/Home/Forbidden"),
        AutomaticAuthenticate = true,
        AutomaticChallenge = true
    });

Here we're using the Cookie authentication, defining our LoginPath, where users will be redirected for authentication, and AccessDeniedPath when the user is not authorized. AutomaticAuthenticate flag indicates that the middleware should run on every request and attempt to validate and reconstruct any serialized principal it created. AutomaticChallenge flag indicates that the middleware should redirect the browser to the LoginPath or the AccessDeniedPath when the authorization fails (there are various other configuration options, however this the bare minimum we need for this example).

Next, we'll configure the requirements for the ReadPolicy. The policy will demand the user to be authenticated and have the Read claim in order access the required resource(s). Depending on your authorization logic, you can setup your policy to require additional claims.

public void ConfigureServices(IServiceCollection services) 
{
    services.AddAuthorization(options =>
    {
        options.AddPolicy("ReadPolicy", policyBuilder =>
        {
            policyBuilder.RequireAuthenticatedUser()
                .RequireAssertion(context => context.User.HasClaim("Read", "true"))
                .Build();
        });
    });
}

6. Finally we need to add the mvc middleware configuration.

app.UseMvc(builder =>
    {
        builder.MapRoute("default", "{controller=Home}/{action=index}/{id?}");
    });

Let's add couple of controllers so that we can test the login and the policy we've created. Create AccountController for user login and HomeController where we'll apply the ReadPolicy.

7. In the AccountController.cs add the following actions to login user;

[HttpGet]
public IActionResult Login(string returnUrl) 
{
    ViewData["ReturnUrl"] = returnUrl;
    return View();
}

8. Add a simple Login.cshtml view under the Views/Account folder (create the folder structure if it doesn't exists) where the user can login to the application.

<form asp-action="Account/Login" method="post" 
      asp-route-returnUrl="@ViewData["ReturnUrl"]">
    <div>
        <label>Username</label>
        <input type="text" name="username" />
    </div>
    <div>
        <label>Password</label>
        <input type="password" name="password" />
    </div>
    <div><button>Login</button></div>
</form> 

In the POST login action, we have a simple verification; The username and the password must match in order to authenticate the user (Obviously you wouldn't do this in a real production application but for our demo purposes this is fine). If they match, we then create a set of claims, the claims identity, and the claims principle that represents the authenticated user. Then, we sign in the user (means we issue a cookie to the user which contains the set of claims we've created) and redirect back to the resource that was requested for access.

[HttpPost]
public async Task<IActionResult> Login(string username, string password, string returnUrl) 
{
    if (username == password)
    {
        var claims = new List<Claim>
        {
            new Claim("Read", "true"),
            new Claim(ClaimTypes.Name, "ayayalar"),
            new Claim(ClaimTypes.Sid, "12345")
        };

        var claimsIdentity = new ClaimsIdentity(claims, "password");
        var claimsPrinciple = new ClaimsPrincipal(claimsIdentity);

        await HttpContext.Authentication.SignInAsync("Cookies", claimsPrinciple);

        if (Url.IsLocalUrl(returnUrl))
        {
            return Redirect(returnUrl);
        }

        return Redirect("~/");
    }

    return View();
}

9. Add the following action to the HomeController.cs;

[Authorize(Policy = "ReadPolicy")]
public IActionResult Index() 
{
    return View();
}

Note that we passed the ReadPolicy to the authorization attribute. The user must be authenticated and have a Read claim to have access. Otherwise, they'll be forwarded to the Forbidden page as we specified in the authentication middleware configuration.

The Index.cshtml view for the home page (can be as simple as one line of code) under Views/Home folder;

<h1>Access Granted</h1>

We should be able to test our changes at this point. Once you run the application, you'll be redirected to the login page since you're not authenticated (notice the return url in the query string is set automatically by the framework). Upon successfully submitting your credentials, you will be authorized and redirected to the home page.

For testing purposes, try removing the Read claim we've added in the Loginaction, rebuild your solution and restart the application, even if the user can login successfully, authorization will be denied and the user will be redirected to the Forbidden page.



European ASP.NET Core Hosting - HostForLIFE.eu :: How to Add Localisation to ASP.NET Core Application

clock January 25, 2017 06:07 by author Scott

In this post I'll walk through the process of adding localisation to an ASP.NET Core application using the recommended approach with resx resource files.

Introduction to Localisation

Localisation in ASP.NET Core is broadly similar to the way it works in the ASP.NET 4.X. By default you would define a number of .resx resource files in your application, one for each culture you support. You then reference resources via a key, and depending on the current culture, the appropriate value is selected from the closest matching resource file.

While the concept of a .resx file per culture remains in ASP.NET Core, the way resources are used has changed quite significantly. In the previous version, when you added a .resx file to your solution, a designer file would be created, providing static strongly typed access to your resources through calls such as Resources.MyTitleString.

In ASP.NET Core, resources are accessed through two abstractions, IStringLocalizer and IStringLocalizer<T>, which are typically injected where needed via dependency injection. These interfaces have an indexer, that allows you to access resources by a string key. If no resource exists for the key (i.e. you haven't created an appropriate .resx file containing the key), then the key itself is used as the resource.

Consider the following example:

using Microsoft.AspNet.Mvc; 
using Microsoft.Extensions.Localization;

public class ExampleClass 
{
    private readonly IStringLocalizer<ExampleClass> _localizer;
    public ExampleClass(IStringLocalizer<ExampleClass> localizer)
    {
        _localizer = localizer;
    }

    public string GetLocalizedString()
    {
        return _localizer["My localized string"];
    }
}

In this example, calling GetLocalizedString() will cause the IStringLocalizer<T> to check the current culture, and see if we have an appropriate resource file for ExampleClass containing a resource with the name/key "My localized string". If it finds one, it returns the localised version, otherwise, it returns "My Localized string".

The idea behind this approach is to allow you to design your app from the beginning to use localisation, without having to do up front work to support it by creating the default/fallback .resx file. Instead, you can just write the default values, then add the resources in later.

Personally, I'm not sold on this approach - it makes me slightly twitchy to see all those magic strings around which are essentially keys into a dictionary. Any changes to the keys may have unintended consequences, as I'll show later in the post.

Adding localisation to your application

For now, I'm going to ignore that concern, and dive in using Microsoft's recommended approach. I've started from the default ASP.NET Core Web application without authentication.

The first step is to add the localisation services in your application. As we are building an MVC application, we'll also configure View localisation and DataAnnotations localisation. The localisation packages are already referenced indirectly by the Microsoft.AspNetCore.MVC package, so you should be able to add the services and middleware directly in your Startup class:

public void ConfigureServices(IServiceCollection services) 
{
    services.AddLocalization(opts => { opts.ResourcesPath = "Resources"; });

    services.AddMvc()
        .AddViewLocalization(
            LanguageViewLocationExpanderFormat.Suffix,
            opts => { opts.ResourcesPath = "Resources"; })
        .AddDataAnnotationsLocalization();
}

These services allow you to inject the IStringLocalizer service into your classes. They also allow you to have localised View files (so you can have Views with names like MyView.fr.cshtml) and inject the IViewLocalizer, to allow you to use localisation in your view files. Calling AddDataAnnotationsLocalizationconfigures the Validation attributes to retrieve resources via an IStringLocalizer.

The ResourcePath parameter on the Options object specifies the folder of our application in which resources can be found. So if the root of our application is found at ExampleProject, we have specified that our resources will be stored in the folder ExampleProject/Resources.

Configuring these classes is all that is required to allow you to use the localisation services in your application. However you will typically also need some way to select what the current culture is for a given request.

To do this, we use the RequestLocalizationMiddleware. This middleware uses a number of different providers to try and determine the current culture. To configure it with the default providers, we need to decide which cultures we support, and which is the default culture.

Note that the configuration example in the documentation didn't work for me, though the Localization.StarterWeb project they reference did, and is reproduced below.

public void ConfigureServices(IServiceCollection services) 
{
    // ... previous configuration not shown

    services.Configure<RequestLocalizationOptions>(
        opts =>
        {
            var supportedCultures = new[]
            {
                new CultureInfo("en-GB"),
                new CultureInfo("en-US"),
                new CultureInfo("en"),
                new CultureInfo("fr-FR"),
                new CultureInfo("fr"),
            };

            opts.DefaultRequestCulture = new RequestCulture("en-GB");
            // Formatting numbers, dates, etc.
            opts.SupportedCultures = supportedCultures;
            // UI strings that we have localized.
            opts.SupportedUICultures = supportedCultures;
        });
}

public void Configure(IApplicationBuilder app) 
{
    app.UseStaticFiles();
    var options = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();    app.UseRequestLocalization(options.Value);

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

Using localisation in your classes

We now have most of the pieces in place to start adding localisation to our application. We don't yet have a way for users to select which culture they want to use, but we'll come to that shortly. For now, lets look at how we go about retrieving a localised string.

Controllers and services

Whenever you want to access a localised string in your services or controllers, you can inject an IStringLocalizer<T> and use its indexer property. For example, imagine you want to localise a string in a controller:

public class HomeController: Controller 
{
    private readonly IStringLocalizer<HomeController> _localizer;

    public HomeController(IStringLocalizer<HomeController> localizer)
    {
        _localizer = localizer;
    }

    public IActionResult Index()
    {
        ViewData["MyTitle"] = _localizer["The localised title of my app!"];
        return View(new HomeViewModel());
    }
}

Calling _localizer[] will lookup the provided string based on the current culture, and the type HomeController. Assuming we have configured our application as discussed previously, the HomeController resides in the ExampleProject.Controllers namespace, and we are currently using the fr culture, then the localizer will look for either of the following resource files:

  • Resources/Controller.HomeController.fr.resx
  • Resources/Controller/HomeController.fr.resx

If a resource exists in one of these files with the key "The localised title of my app!" then it will be used, otherwise the key itself will be used as the resource. This means you don't need to add any resource files to get started with localisation - you can just use the default language string as your key and come back to add .resx files later.

Views

There are two kinds of localisation of views. As described previously, you can localise the whole view, duplicating it and editing as appropriate, and providing a culture suffix. This is useful if the views need to differ significantly between different cultures.

You can also localise strings in a similar way to that shown for the HomeController. Instead of an IStringLocalizer<T>, you inject an IViewLocalizer into the view. This handles HTML encoding a little differently, in that it allows you to store HTML in the resource and it won't be encoded before being output. Generally you'll want to avoid that however, and only localise strings, not HTML.

The IViewLocaliser uses the name of the View file to find the associated resources, so for the HomeController's Index.cshtml view, with the fr culture, the localiser will look for:

  • Resources/Views.Home.Index.fr.resx
  • Resources/Views/Home/Index.fr.resx

The IViewLocalizer is used in a similar way to IStringLocalizer<T> - pass in the string in the default language as the key for the resource:

@using Microsoft.AspNetCore.Mvc.Localization
@model AddingLocalization.ViewModels.HomeViewModel
@inject IViewLocalizer Localizer
@{
    ViewData["Title"] = Localizer["Home Page"];
}
<h2>@ViewData["MyTitle"]</h2> 

DataAnnotations

One final common area that needs localisation is DataAnnotations. These attributes can be used to provide validation, naming and UI hints of your models to the MVC infrastructure. When used, they provide a lot of additional declarative metadata to the MVC pipeline, allowing selection of appropriate controls for editing the property etc.

Error messages for DataAnnotation validation attributes all pass through an IStringLocalizer<T> if you configure your MVC services using AddDataAnnotationsLocalization(). As before, this allows you to specify the error message for an attribute in your default language in code, and use that as the key to other resources later.

public class HomeViewModel 
{
    [Required(ErrorMessage = "Required")]
    [EmailAddress(ErrorMessage = "The Email field is not a valid e-mail address")]
    [Display(Name = "Your Email")]
    public string Email { get; set; }
}

Here you can see we have three DataAnnotation attributes, two of which are ValidationAttributes, and the DisplayAttribute, which is not. The ErrorMessage specified for each ValidationAttribute is used as a key to lookup the appropriate resource using an IStringLocalizer<HomeViewModel>. Again, the files searched for will be something like:

  • Resources/ViewModels.HomeViewModel.fr.resx
  • Resources/ViewModels/HomeViewModel.fr.resx

A key thing to be aware of is that the DisplayAttribute is not localised using the IStringLocalizer<T>. This is far from ideal, but I'll address it in my next post on localisation.

Allowing users to select a culture

With all this localisation in place, the final piece of the puzzle is to actually allow users to select their culture. The RequestLocalizationMiddleware uses an extensible provider mechanism for choosing the current culture of a request, but it comes with three providers built in

  • QueryStringRequestCultureProvider
  • AcceptLanguageHeaderRequestCultureProvider
  • CookieRequestCultureProvider

These allow you to specify a culture in the querystring (e.g ?culture=fr-FR), via the Accept-Languageheader in a request, or via a cookie. Of the three approaches, using a cookie is the least intrusive, as it will obviously seamlessly be sent with every request, and does not require the user to set the Accept-Language header in their browser, or require adding to the querystring with every request.

Again, the Localization.StarterWeb sample project provides a handy implementation that shows how you can add a select box to the footer of your project to allow the user to set the language. Their choice is stored in a cookie, which is handled by the CookieRequestCultureProvider for each request. The provider then sets the CurrentCulture and CurrentUICulture of the thread for the request to the user's selection.

To add the selector to your application, create a partial view _SelectLanguagePartial.cshtml in the Shared folder of your Views:

@using System.Threading.Tasks
@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Options

@inject IViewLocalizer Localizer
@inject IOptions<RequestLocalizationOptions> LocOptions

@{
    var requestCulture = Context.Features.Get<IRequestCultureFeature>();
    var cultureItems = LocOptions.Value.SupportedUICultures
        .Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
        .ToList();
}

<div title="@Localizer["Request culture provider:"] @requestCulture?.Provider?.GetType().Name"> 
    <form id="selectLanguage" asp-controller="Home"
          asp-action="SetLanguage" asp-route-returnUrl="@Context.Request.Path"
          method="post" class="form-horizontal" role="form">
        @Localizer["Language:"] <select name="culture"
                                        asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems"></select>
        <button type="submit" class="btn btn-default btn-xs">Save</button>

    </form>
</div> 

We want to display this partial on every page, so update the footer of your _Layout.cshtml to reference it:

<footer> 
    <div class="row">
        <div class="col-sm-6">
            <p>&copy; 2016 - Adding Localization</p>
        </div>
        <div class="col-sm-6 text-right">
            @await Html.PartialAsync("_SelectLanguagePartial")
        </div>
    </div>
</footer> 

Finally, we need to add the controller code to handle the user's selection. This currently maps to the SetLanguage action in the HomeController:

[HttpPost]
public IActionResult SetLanguage(string culture, string returnUrl) 
{
    Response.Cookies.Append(
        CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
        new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
    );

    return LocalRedirect(returnUrl);
}

And that's it! If we fire up the home page of our application, you can see the culture selector in the bottom right corner. At this stage, I have not added any resource files, but if I trigger a validation error, you can see that the resource key is used for the resource itself:

My development flow is not interrupted by having to go and mess with resource files, I can just develop the application using the default language and add resx files later in development. If I later add appropriate resource files for the fr culture, and a user changes their culture via the selector, I can see the effect of localisation in the validation attributes and other localised strings:

As you can see, the validation attributes and page title are localised, but the label field 'Your Email' has not, as that is set in the DisplayAttribute.

Summary

In this post I showed how to add localisation to your ASP.NET Core application using the recommended approach of providing resources for the default language as keys, and only adding additional resources as required later.

In summary, the steps to localise your application are roughly as follows:

1. Add the required localisation services
2. Configure the localisation middleware and if necessary a culture provider

3. Inject IStringLocalizer<T> into your controllers and services to localise strings

4. Inject IViewLocalizer into your views to localise strings in views

5. Add resource files for non-default cultures

6. Add a mechanism for users to choose their culture



European ASP.NET Core Hosting - HostForLIFE.eu :: Dependency Injection in ASP.NET Core

clock January 16, 2017 11:12 by author Scott

One of the nice things that the new ASP.NET Core stack brings to the table, is Dependency Injection (DI) as a first-class citizen, right out of the box. DI is nothing new, even for ASP.NET, but in the earlier versions, it wasn't baked into the platform, and developers were forced to jump through hoops in order to enable it.

Let's look at the status quo and how things are changing for the better with the new DI system in ASP.NET Core...

Status quo

Because of the history of ASP.NET, the timelines and factoring of its different products, like WebForms, MVC, SignalR, Katana (OWIN) and Web API, they've each had their own way of doing DI. Some products have extensibility points that you can leverage in order to plug in an Inversion of Control (IoC) container:

  • Web API: System.Web.Http.Dependencies.IDependencyResolver and System.Web.Http.Dependencies.IDependencyScope
  • MVC: System.Web.Mvc.IDependencyResolver
  • SignalR: Microsoft.AspNet.SignalR.IDependencyResolver

While others, like WebForms and Katana, doesn't. Some will argue that the IDependencyResolver-type abstraction, which is essentially an implementation of the Service Locator pattern, is an anti-pattern and should be avoided, but that's a discussion for another day.

There are also other ways of achieving DI within some of the frameworks; MVC has IControllerFactory and IControllerActivator, Web API has IHttpControllerActivator etc. All of these are extensibility points that you can implement in order to leverage DI in your controllers.

Implementing these abstractions yourself isn't something that you typically want or should have to do. Most IoC containers have already implemented these adapters for you and ship them as NuGet packages. If we take Autofac as an example, some adapters include

  • Autofac.Mvc4
  • Autofac.Mvc5
  • Autofac.Owin
  • Autofac.WebApi
  • Autofac.WebApi2
  • Autofac.SignalR
  • Autofac.Web (WebForms)

As you can see, it quickly starts to add up - and this is just for a single container! Imagine if I'd compiled a list for the gazillion different IoC containers in the .NET space. Each of the adapters needs to be maintained, updated, versioned etc. That's a big burden on the adapter maintainers and the community in general.

On the consuming side of this, for a typical web application using MVC, SignalR and Web API, you'd end up needing three (or more) of these adapters, in order to leverage DI across the application.

The future

Even though a lot of ideas and code have been carried forward from Katana, ASP.NET Core is by all means a re-imagining, re-write, re-EVERYTHING of the entire, current ASP.NET stack. Hell, it's even triggered a re-jigging of the entire .NET (Core) platform and tooling. This means that it's a perfect time to bring DI into the platform itself, and make all components on top benefit of a single, unified way of doing DI.

Say hello to IServiceProvider! Even though the interface itself isn't new (it's been living in mscorlib under the System namespace since .NET 1.1), it's found new life in the ASP.NET Core DI system. It's also accompanied by a couple of new interfaces; IServiceCollection, which is essentially a builder for an IServiceProvider and IServiceScope, which is intended for resolving services within a specific lifetime scope, like per-request.

In order for things to Just Work™, out of the box, Microsoft have implemented a lightweight IoC container that ships with the ASP.NET Core hosting layer. It's in the Microsoft.Extensions.DependencyInjection NuGet package.

When ASP.NET Core is bootstrapped, it creates an instance of IServiceCollection and passes it to user code using the ConfigureServicesmethod of the Startup class:

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

         // Adds the services MVC requires to run.
        services.AddMvc();

        // Add some custom services
        services.AddSingleton<ICache, Cache>();
        services.AddScoped<IDatabaseSession, DatabaseSession>();
    }

    // ...
}

In this method, you're free to add whatever services your application needs, and they will magically be available for constructor injection across the board. Different components in the stack also ship with extension methods to conveniently add the services the component needs to the collection, like AddMvc (shown above), AddCors, AddEntityFramework etc.

Now, it's important to note that the default implementation, living in Microsoft.Extensions.DependencyInjection is a deliberately lightweight, feature poor (is that a word?), fast, implementation of an IoC container. It has just the amount of features needed for the runtime/platform/framework to compose itself and run. A "lowest common denominator" feature set, if you will. If you want more advanced features, like many do, Microsoft actively encourages you to Bring Your Own Container (BYOC), or layer the functionality on top, which I've done with Scrutor. This brings us back to IoC container adapters.

If you want to use a third party container, you have to, like before, implement your own version of IServiceProvider (and its accompanying interfaces), or use an adapter that someone in the community has already provided. There are already several of these available, like

The difference this time is that you only need a single adapter to enable DI across the board. To plug in the adapter, you have to change the return type of the ConfigureServicesmethod to IServiceProvider and return the adapter implementation. By using StructureMap.Dnx as an example, let's look at our startup class again:

public class Startup 
{
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        // This method gets called by the runtime.
        // Use this method to add services to the container.

        // Adds the services MVC requires to run.
        services.AddMvc();

        // Add some custom services
        services.AddSingleton<ICache, Cache>();
        services.AddScoped<IDatabaseSession, DatabaseSession>();

        // Create an instance of a StructureMap container.
        var container = new Container();

        // Here we can add stuff to container, using StructureMap-specific APIs...

        // Populate the StructureMap container with
        // services from the IServiceCollection.
        container.Populate(services);

        // Resolve the StructureMap-specific IServiceProvider
        // and return it to the runtime.
        return container.GetInstance<IServiceProvider>();
    }

    // ...
}

By doing this, all components will resolve its services from the StructureMap container, and you'll be able to utilize the full feature set of StructureMap, like awesome diagnostics, property injection, convention based registrations, profiles, decoration etc.

This post turned out longer than I expected, just to show a couple of lines of code at the end, but I thought it would be interesting to put everything in perspective and hopefully you did too. As you can see the DI story has been greatly simplified in the this new world, while still allowing you, as an application, library or framework developer, to utilize DI across the board, with minimal effort.

 

 



European ASP.NET SignalR Hosting - HostForLIFE.eu :: Using ASP.NET SignalR for Chat Application

clock December 5, 2016 10:04 by author Scott

ASP.Net SignalR is one of the major revolutions in the development technology world these days for creating real applications. Consider an application having a page where you are required to update the user interface with the latest data, as soon as it is available. Such applications are said to be real-time applications, where the UI is updated as soon as the latest data is available for the user.

The best example is a stock market application that must maintain the user interface updated with the data as soon as the stock rates are changed. Another example is a chat application that updates the receiver with the latest message, from the sender. Some of the techniques could use timer-based requests to the server for getting the data and some could use polling to get the data. A good alternative to these is SignalR. 

As we know, our model of the web applications mainly consists of a server that hosts the application and the client, representing the end users of the applications. For creating SignalR based applications, we need to create a hub on the server that is responsible for updating the client or the end users with the latest data. This hub is nothing but a simple class inheriting from the Hub class. At the client end, we get an automatically generated JavaScript based proxy file (at run time) that can be used by the client for connecting with the hub. The client code also contains a JavaScript function that the hub uses to provide them the latest data.

To explain this process in detail, our hub directly calls the client JavaScript functions, to provide the latest data. On the other hand, by using the auto-generated JavaScript proxy file at the client end, client code can uses this proxy, to call the methods of the server hub, if required. The term if required is used here deliberately with the fact that the client may not be required to call the hub. For example, in an application where we have a user dashboard with some data from a database, we can use SqlDependency and SignalR to keep the user interface updated, whenever there is any change in the database records. In this case, the client is not required to make any calls to the server for getting the updates. On the other hand, if we have a chat application, the client code will call the server hub and forward the message. The Hub will than broadcast this message to the users of the application, by calling the JavaScript method of the clients.

One very important point from the preceding paragraph is that the client never calls the hub for getting the latest data. The client may only call the hub so that the hub can forward the message to the other connected clients. If the client code needs to make the calls for the latest data to the server, than the entire purpose of using the SignalR fails and we could have used the old concepts of a timer or page refresh for this.

Build Simple Group Chat Application in 15 minutes Using SignalR

Yes, that's correct. Once you are familiar with the basic concept/flow of SignalR, you can do it very easily. We will be now creating a group chat, without the use of a database. If we think about the flow of the application, this entire process requires a client to send a message to the server that will broadcast this message to all the connected client users. So the server needs to have a component that can broadcast the message to the clients. This role is played by the hub class.

Create a new project named SignalRChat. Add the references to the SignalR libraries using Nuget. It will automatically add the references to the OWIN hosting option libraries that allow addition of the SignalR application to the OWIN pipeline. Apart from the server libraries, it also adds the client libraries required for using SignalR. See the following references that are to be added:

Create OWIN host for the application

We will be using the OWIN based hosting, to host this application. Without going into depth about the OWIN hosting, let's add a class named Startup.cs. The name must be Startup as in the OWIN based hosting specifications and its namespace must be decorated with the assembly attribute, specifying that the Startup assembly is the starting point of the application. Next we define a method named Configuration and register the SignalR in the OWIN pipeline using app.MapSignalR().

Create the Hub on the Server

Our next step is to create the hub on the server that is nothing but a class file. We will name it SignalRChatHub and derive from the Hub class. It will contain a method named BroadCastMessage, with 2 parameters. the client code will use this method (using the proxy generated at its end) for communication with the hub and the parameters as the data to be sent to the hub. Inside this method, use the Clients property of the Hub class to call the client-side function. This function is a simple JavaScript function that will receive the data sent by the hub and update the chat window of the user. We will define a function with the name receiveMessage at the client end (later in the code). So for now, we will use this method name.

A point to be noted here is that we will not get any intelligence help for the client methods, of course. This method will be dynamically resolved. See the image below:

Setup the Client code

The server setup is done. We will now add an HTML page named ChatWindow.html that will be our chat window for the user. Also we add the references to the jquery-1.6.4.min.js and jquery.signalR-2.2.0 .min,js on this page that were added by the Nuget package manager. Earlier we discussed that SignalR automatically generates a proxy class at run time, for client code, to connect with the hub. So we also need to reference this file. Since this file is generated at run time, it does not exist physically for us. As in the SignalR tutorials on the official ASP.Net website, it states:

SignalR creates the JavaScript code for the proxy on the fly and serves it to the client in response to the "/signalr/hubs" URL.

So we need to add this reference also.

We also have the option to disable this auto-generated proxy file generation (that is out of scope for this discussion) and create the proxy ourselves. In that case, we need to reference that file accordingly. Next, let's add some HTML mark-up to generate the chat window and design it using CSS styling.

Now it's time for the client code to connect with the hub and send the message, so that hub can broadcast to all the users. For this, we first get the proxy instance in a variable named chatProxy. Note the camel case syntax of the client code below. This is the convention to be followed when creating the SignalR application. For detailed specifications, I recommend you check out the ASP.Net official SignalR website. Without going further into the details, let's move forward with the code. Here, signalRChatHub is the name of the hub on the server (that we created on the server earlier).

Next, we attach the button click event (the button to send the message to the users), when the connection to the hub is successfully started. This event will call the method of the hub, using the proxy instance that will receive the message and broadcast it to users. See the code below:

We also declare the function to which the hub will call, when it needs to update all the users with the message received. This is the function name we referred to, from the hub method, at the start of the discussion. So this function acts as a type of callback function here.

So all the client code is also set up and we can now run the application. So our complete client code will now look as in:

We can now run the application. Copy the URL and open another instance of the browser or any other browser and we can start chatting.

 



About HostForLIFE.eu

HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2016 Hosting, ASP.NET Core 2.2.1 Hosting, ASP.NET MVC 6 Hosting and SQL 2017 Hosting.


Tag cloud

Sign in