All About ASP.NET and ASP.NET Core 2 Hosting BLOG

Tutorial and Articles about ASP.NET and the latest ASP.NET Core

ASP.NET Core 3 Hosting :: ASP.NET Core 3 Preview

clock February 26, 2019 06:50 by author Jervis

ASP.NET Core 3.0 App with .NET Core 3.0 preview 2 release

Before we create the application, first we need to install Visual Studio 2019 and .NET Core 3.0. Let’s first install .NET Core 3.0 SDK.

Installing .NET Core 3.0

To download .NET Core 3.0 preview 2, visit this link. Based on your platform, download the appropriate installer. Once the download is complete, run the installer to install .NET Core 3.0 on your system. The .NET Core 3.0 preview installation will not impact your existing .NET Core version installation.

Installing Visual Studio 2019 Preview

To install Visual Studio 2019 preview, download the installer from this location. Don’t worry. Visual Studio and Visual Studio “Preview” can be installed side-by-side on the same device. It will have no impact on your current stable VS installation.

Visual Studio 2019 offers a completely new project creation experience. Once the installation is complete, let’s open the Visual Studio 2019 preview and create the ASP.NET Core 3.0 app. Select the ASP.NET Core Web Application template.

When you click Ok, you will get the following prompt. Select ASP.NET Core 3.0 and choose the MVC template.

The Visual Studio will create an ASP.NET Core 3.0 based MVC project. The solution structure looks similar to the previous version of ASP.NET Core. However, there is one change with respect to dependencies reference, which is the Microsoft.AspNetCore.Mvc.NewtonsoftJson nuget package.

 

ASP.NET Core shared framework (Microsoft.AspNetCore.App) will only contain first-party assemblies that are fully developed, supported, and serviceable by Microsoft. As part of this change, the following sub-components will be removed from shared framework.

  • Json.NET (Newtonsoft.Json)
  • Entity Framework Core (Microsoft.EntityFrameworkCore.*)
  • Microsoft.CodeAnalysis (Roslyn)

The project file is now targeting to .NET Core 3.0 and also has a reference of Microsoft.AspNetCore.Mvc.NewtonsoftJson package.

<Project Sdk="Microsoft.NET.Sdk.Web"> 

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup> 

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.0-preview-19075-0444" />
  </ItemGroup> 

</Project>

Let’s take a look at the code level changes.

1. Open the Program.cs and you will see the following code. The ASP.NET Core 3.0 templates use Generic Host. Previous versions used Web Host.

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    } 

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

The goal of the Generic Host is to decouple the HTTP pipeline from the Web Host API to enable a wider array of host scenarios. Messaging, background tasks, and other non-HTTP workloads based on the Generic Host benefit from cross-cutting capabilities, such as configuration, dependency injection (DI), and logging.

The above code uses webBuilder which is a type of IWebHostBuilder interface used with WebHostBuilder. But it will be deprecated and eventually its functionality will be replaced by HostBuilder, though the interface will remain.

The biggest difference between WebHostBuilder and HostBuilder is that you can no longer inject arbitrary services into your Startup.cs. Instead, you will be limited to the IHostingEnvironment and IConfiguration interfaces. This removes a behavior quirk related to injecting services into Startup.cs before the ConfigureServices method is called.

2. As mentioned earlier, Json.NET is removed from the shared framework and now needs to be added as a package. Open Startup.cs and take a look at ConfigureServices method

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    }); 

    services.AddMvc()
        .AddNewtonsoftJson();
}

3. There are some updates to EndPoint routing introduced with ASP.NET Core 2.2. Endpoint routing allows frameworks like MVC as well as other routable things to mix with middleware in a way that hasn’t been possible before. With this, routing decisions can occur earlier into the pipeline so that incoming requests can be mapped to their eventual endpoint before MVC is even invoked. This is now present in the project templates in 3.0.0-preview-2 (Startup.cs -> Configure()).

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

Here, the app.UseRouting() call adds a new Endpoint Routing middleware. The UseRouting replaces many of the features that were implemented inside UseMvc() in the past. The MapApplication() brings in MVC controllers and pages for routing and MapControllerRoutedefines the default route.

That’s it for now

Summary

ASP.NET Core 3.0 will bring some code breaking changes and some of them are available with this preview 2 release. The change regarding ASP.NET Core shared framework to include only those libraries which are developed, supported, and serviceable by Microsoft will definitely reduce the application size by a few bytes. It is the right time to play around ASP.NET Core 3.0 and expect some more changes when the final version comes out.



ASP.NET Core Hosting :: How to Send and Receive Email in ASP.NET Core Using Mailkit

clock February 18, 2019 07:36 by author Jervis

Creating An Email Service

It’s always good practice that when you add in a new library, that you build an abstraction on top of it. If we take MailKit as an example, what if MailKit is later superceded by a better emailing library? Will we have to change references all over our code to reference this new library? Or maybe MailKit has to make a breaking change between versions, will we then have to go through our code fixing all the now broken changes?

Another added bonus to creating an abstraction is that it allows us to map out how we want our service to look before we worry about implementation details. We can take a very high level view of sending an email for instance without having to worry about exactly how MailKit works. Because there is a lot of code to get through, I won’t do too much explaining at this point, we will just run through it. Let’s go!

First, let’s go ahead and create an EmailAddress class. This will have only two properties that describe an EmailAddress.

public class EmailAddress
{
                public string Name { get; set; }
                public string Address { get; set; }
}

Now we will need something to describe a simple EmailMessage. There are a tonne of properties on an email, for example attachments, CC, BCC, headers etc but we will break it down to the basics for now. Containing all of this within a class means that we can add extra properties as we need them later on.

public class EmailMessage
{
                public EmailMessage()
                {
                                ToAddresses = new List<EmailAddress>();
                                FromAddresses = new List<EmailAddress>();
               

                public List<EmailAddress> ToAddresses { get; set; }
                public List<EmailAddress> FromAddresses { get; set; }
                public string Subject { get; set; }
                public string Content { get; set; }
}

Now we need to setup our email configuration. That’s our SMTP servers, ports, credentials etc. For this we will make a simple settings class to hold all of this. Since we are good programmers we will use an interface too!

public interface IEmailConfiguration
{
                string SmtpServer { get; }
                int SmtpPort { get; }
                string SmtpUsername { get; set; }
                string SmtpPassword { get; set; } 

                string PopServer { get; }
                int PopPort { get; }
                string PopUsername { get; }
                string PopPassword { get; }


public class EmailConfiguration : IEmailConfiguration
{
                public string SmtpServer { get; set; }
                public int SmtpPort  { get; set; }
                public string SmtpUsername { get; set; }
                public string SmtpPassword { get; set; } 

                public string PopServer { get; set; }
                public int PopPort { get; set; }
                public string PopUsername { get; set; }
                public string PopPassword { get; set; }
}

Now we actually need to load this configuration into our app. In your appsettings.json, you need to add a section at the root for email settings. It should look something like this :

{
  "EmailConfiguration": {
    "SmtpServer": "smtp.myserver.com",
    "SmtpPort": 465,
    "SmtpUsername": "smtpusername",
    "SmtpPassword": "smtppassword", 

    "PopServer": "popserver",
    "PopPort": 995,
    "PopUsername": "popusername",
    "PopPassword" :  "poppassword"
  }
  ....Other settings here...
}

In the ConfigureServices method or your startup.cs, we can now pull out this configuration and load it into our app with a single line.

public void ConfigureServices(IServiceCollection services)
{
                services.AddMvc();

services.AddSingleton<IEmailConfiguration>(Configuration.GetSection("EmailConfiguration").Get<EmailConfiguration>());
}

This allows us to inject our configuration class anywhere in our app.

The final piece of the puzzle is a simple email service that can be used to send and receive email. Let’s create an interface and an implementation that’s empty for now. The implementation should accept our settings object as a constructor.

public interface IEmailService
{
                void Send(EmailMessage emailMessage);
                List<EmailMessage> ReceiveEmail(int maxCount = 10);


public class EmailService : IEmailService
{
                private readonly IEmailConfiguration _emailConfiguration;

                public EmailService(IEmailConfiguration emailConfiguration)
                {
                                _emailConfiguration = emailConfiguration;
               

                public List<EmailMessage> ReceiveEmail(int maxCount = 10)
                {
                                throw new NotImplementedException();
               

                public void Send(EmailMessage emailMessage)
                {
                                throw new NotImplementedException();
                }
}

Head back to our ConfigureServices method of our startup.cs to add in a final line to inject in our EmailService everywhere.

public void ConfigureServices(IServiceCollection services)
{
                services.AddMvc();
services.AddSingleton<IEmailConfiguration>(Configuration.GetSection("EmailConfiguration").Get<EmailConfiguration>());
                services.AddTransient<IEmailService, EmailService>();
}

Phew! And we are done. If at this point we decided MailKit isn’t for us, we still have an email service that can swap in and out libraries as it needs to, and our calling application doesn’t need to worry about what’s going on under the hood. That’s the beauty of abstracting a library away!

Getting Started With MailKit

Getting started with MailKit is as easy as installing a Nuget package. Simply run the following from your Package Manager Console :

Install-Package MailKit

And hey presto! You now have access to MailKit in your application

Sending Email via SMTP With MailKit

Let’s head back to our email service class and fill out the “Send” method with the actual code to send an email via MailKit. The code to do this is below :

public void Send(EmailMessage emailMessage)
{
                var message = new MimeMessage();
                message.To.AddRange(emailMessage.ToAddresses.Select(x => new MailboxAddress(x.Name, x.Address)));
                message.From.AddRange(emailMessage.FromAddresses.Select(x => new MailboxAddress(x.Name, x.Address))); 

                message.Subject = emailMessage.Subject;
                //We will say we are sending HTML. But there are options for plaintext etc.
                message.Body = new TextPart(TextFormat.Html)
                {
                                Text = emailMessage.Content
                }; 

                //Be careful that the SmtpClient class is the one from Mailkit not the framework!
                using (var emailClient = new SmtpClient())
                {
                                //The last parameter here is to use SSL (Which you should!)
                                emailClient.Connect(_emailConfiguration.SmtpServer, _emailConfiguration.SmtpPort, true); 

                                //Remove any OAuth functionality as we won't be using it.
                                emailClient.AuthenticationMechanisms.Remove("XOAUTH2"); 

                                emailClient.Authenticate(_emailConfiguration.SmtpUsername, _emailConfiguration.SmtpPassword); 

                                emailClient.Send(message);
                                emailClient.Disconnect(true);
                }                             

}

The comments should be pretty self explanatory, but let’s quickly run through it.

  • You can send clear text or HTML emails depending on the “TextFormat” you use when creating your message body
  • MailKit has named it’s Smtp class “SmtpClient” which is the same as the framework class. Be careful if you are using Resharper and the like that when you click “Add Reference” you are adding the correct reference.
  • You should choose to use SSL whenever available when connecting to the SMTP Server

Because we built out our EmailService, EmailMessage and EmailConfiguration classes earlier, they are all ready to be used immediately!

Receiving Email via POP With MailKit

And now the code to receive email via POP.

public List<EmailMessage> ReceiveEmail(int maxCount = 10)
{
                using (var emailClient = new Pop3Client())
                {
                                emailClient.Connect(_emailConfiguration.PopServer, _emailConfiguration.PopPort, true); 

                                emailClient.AuthenticationMechanisms.Remove("XOAUTH2"); 

                                emailClient.Authenticate(_emailConfiguration.PopUsername, _emailConfiguration.PopPassword); 

                                List<EmailMessage> emails = new List<EmailMessage>();
                                for(int i=0; i < emailClient.Count && i < maxCount; i++)
                                {
                                                var message = emailClient.GetMessage(i);
                                                var emailMessage = new EmailMessage
                                                {
                                                                Content = !string.IsNullOrEmpty(message.HtmlBody) ? message.HtmlBody : message.TextBody,
                                                                Subject = message.Subject
                                                };
                                                emailMessage.ToAddresses.AddRange(message.To.Select(x => (MailboxAddress)x).Select(x => new EmailAddress { Address = x.Address, Name = x.Name }));
                                                emailMessage.FromAddresses.AddRange(message.From.Select(x => (MailboxAddress)x).Select(x => new EmailAddress { Address = x.Address, Name = x.Name }));
                               

                                return emails;
                }
}

Again, all rather straight forward.

While we only retrieve a few basic details about the email message, the actual MailKit email object has a tonne of data you can inspect including headers, CC addresses, etc. Extend as you need to!



ASP.NET Core Hosting :: How to Set Headers and HTTP Status Codes in ASP.NET Core

clock February 7, 2019 11:36 by author Jervis

I was working on an interesting issue in an ASP.NET Core recently. An external framework was responsible for creating an HTTP Response, and I was only in control of a little component that customized some internal behaviours (via a relevant extensibility point), without being able to influence the final response sent over HTTP.

This is common if you think about extending things like CMS systems or specialized services like for example Identity Server. In those situations, more often than not, the framework would be highly opinionated in what it is trying to do at the HTTP boundaries and as a result, trying to override the HTTP status codes or headers it produces may not be easy.

Let’s have a look at a simple generic workaround.

TL;DR

In ASP.NET Core you can hook a callback to the HTTP response object, which allows you to run arbitrary code just before the response starts getting sent or as soon as it has been sent. This allows you to override status code, headers or even change the response body even if your code is not responsible for flushing the response

// always set the status code to 418
response.OnStarting(() =>
{
    response.StatusCode = 418;
    return Task.CompletedTask;
});

The problem

To illustrate the problem better, let’s have a look at a concrete example – and I think Identity Server is a good choice here.

Identity Server allows you to register your own validators for various authentication grant types – for example client credentials grant, resource owner or even your own custom extension grant.

An implementation of such custom validator could like this:

public class MyResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
    public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
    {
        var user = await UserStore.FindAndValidate(context.UserName, context.Password); 

        if (user == null || !user.IsValid())
        {
            // reject as the credentials are incorrect or account invalid
            context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest, "Invalid username or password.");
            return;
        }        

        if (!user.IsCountrySupported())
        {
            // reject as the country of the user is not allowed
            context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest, "Country not supported.");
            return;
        }        

        // allow
        context.Result = new GrantValidationResult(user.Id, "password", user.Claims, "idsrv");
    }
}

In other words, we validate the user, and allow the token to be issued if the username and password are correct. If not, we will produce a token request error; in addition to that we also produce a different error if the user credentials are correct but the country is not supported.

This is all nice and fine. We have no touchpoints to the HTTP response here, as Identity Server (or any other framework/service that we might be using) would take care of that for us. We only produce the result that we are mandated to produce by the contract – a GrantValidationResult in this case.

It works well in most situations. However, let’s imagine that we’d like to influence the HTTP status codes being returned from this validation code. At the moment the status codes are hidden from us, and it is the responsibility of Identity Server to produce them.

In our case, the Identity Server would actually be returning 2 different ones:

  • GrantValidationResult(user.Id, “password”, user.Claims, “idsrv”) would obviously produce a 200 and result in a token being sent to the user
  • GrantValidationResult(TokenRequestErrors.InvalidRequest, “{ERROR DESCRIPTION}”) would produce a 400 and convey the error description to the caller in the error_description JSON property of the response (as defined by the spec).

Now let’s imagine the situation, that for the code path of user.IsCountrySupported(), we’d like to use HTTP status code 451 instead. This is allowed by the spec, which states “the authorization server responds with an HTTP 400 (Bad Request) status code (unless specified otherwise)”. However, such status code customization is currently not supported by Identity Server.

Let’s have a look at addressing this via a neat ASP.NET Core feature. Before we get there – in case you don’t agree with this spec interpretation – remember that this is merely an example to illustrate that ASP.NET Core feature.

Wrong way to deal with it

There are several ideas of dealing with this, that come to mind straight away.

One naive approach would be to try to throw an exception, let it bubble up as far as possible and then handle it in a way that you can convert the response to the relevant HTTP status code (perhaps with a global handler registered in your Startup class). This, however, wouldn’t work with Identity Server, as it handles all exceptions in the pipeline on its own, without letting it bubble up. In fact, this would typically be the case with most frameworks or services of that sort, not to mention using exceptions for flow control is iffy at best.

Another approach could be to try to write a middleware component, that runs at the end of HTTP pipeline (so wraps the Identity Server middleware) and use it to change the status code. This seems like a great idea at first, but unfortunately it wouldn’t work.

The reason for that is that ASP.NET Core would flush the headers of the response as soon as the first body write happens, and Identity Server, in its pipeline, would start writing to the body already. This means that even though you can technically (there would be no exception thrown for that) change the status code on the response, or inject some headers into it using a custom middleware that runs at the end of the pipeline, that would have no effect on the response anymore, as it is simply too late. You can actually normally see that on the response object by inspecting the response.HasStarted property – at that moment status code and headers modifications are not possible anymore.

One other idea could be to hijack the response writing completely. Since you can inject IHttpContextAccessor to any class, anywhere in the ASP.NET Core application, you can fairly easily get a hold of the HttpResponse. This allows you to simply write to the HTTP response directly. Such approach could possibly work but it is not very elegant to say the least. It would require you to correctly produce the entire set of headers (also the more esoteric ones like Cache-Control and so on) and the status code correctly and flush it before Identity Server can do that, allowing it to only complete the response by writing the body. This is very error prone and very unmaintainable.

Simple solution

A simple and elegant solution is to leverage a little known feature of ASP.NET Core – the ability to register your own callback on the HttpResponse, that would run as soon as the response is started to be sent (or as soon as its completed).

The following hooks exist on the HttpResponse:

/// <summary>
/// Adds a delegate to be invoked just before response headers will be sent to the client.
/// </summary>
/// <param name="callback">The delegate to execute.</param>
/// <param name="state">A state object to capture and pass back to the delegate.</param>
public abstract void OnStarting(Func<object, Task> callback, object state); 

/// <summary>
/// Adds a delegate to be invoked just before response headers will be sent to the client.
/// </summary>
/// <param name="callback">The delegate to execute.</param>
public virtual void OnStarting(Func<Task> callback) => OnStarting(_callbackDelegate, callback); 

/// <summary>
/// Adds a delegate to be invoked after the response has finished being sent to the client.
/// </summary>
/// <param name="callback">The delegate to invoke.</param>
/// <param name="state">A state object to capture and pass back to the delegate.</param>
public abstract void OnCompleted(Func<object, Task> callback, object state); 

/// <summary>
/// Adds a delegate to be invoked after the response has finished being sent to the client.
/// </summary>
/// <param name="callback">The delegate to invoke.</param>
public virtual void OnCompleted(Func<Task> callback) => OnCompleted(_callbackDelegate, callback);

This means we can simply register a delegate that would change the HTTP Status Code, modify the headers and possibly even meddle with the response body, from any point in the ASP.NET Core application. Then, as soon as the response starts being sent (irrespective to the fact which component or part of the pipeline triggered that), our code would run, allowing us to influence the structure of that response.

It is extremely convenient, as we are able to create de facto extensibility points for 3rd party applications, frameworks or services (like Identity Server), in places where they normally don’t exist.

In our case, the final code looks like this:

public static class HttpResponseExtensions
{
    public static void SetHttpStatusCodeOverride(this HttpResponse response, int httpStatusCode)
    {
        response.OnStarting(() =>
        {
            response.StatusCode = httpStatusCode;
            return Task.CompletedTask;
        });
    }


public class MyResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
   private readonly IHttpContextAccessor _httpContextAccessor;  

   public MyResourceOwnerPasswordValidator(IHttpContextAccessor httpContextAccessor)
   {
       _httpContextAccessor = httpContextAccessor;
   } 

    public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
    {
        var user = await UserStore.FindAndValidate(context.UserName, context.Password); 

        if (user == null || !user.IsValid())
        {
            // default 400
            // reject as the credentials are incorrect or account invalid
            context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest, "Invalid username or password.");
            return;
        }        

        if (!user.IsCountrySupported())
        {
            // overridden to 451
            // reject as the country of the user is not allowed
           _httpContextAccessor.HttpContext.Response.SetHttpStatusCodeOverride(451);
            context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest, "Country not supported.");
            return;
        }        

        // allow
        context.Result = new GrantValidationResult(user.Id, "password", user.Claims, "idsrv");
    }
}

I hope you will find this technique useful – I used Identity Server as an example, because it actually solves a real world problem here – but I think you could apply this approach in various places where you’d like to have a certain response-based extensibility point and it’s simply not available.



Cheap ASP.NET 4.5 Hosting

We’re a company that works differently to most. Value is what we output and help our customers achieve, not how much money we put in the bank. It’s not because we are altruistic. It’s based on an even simpler principle. "Do good things, and good things will come to you".

Success for us is something that is continually experienced, not something that is reached. For us it is all about the experience – more than the journey. Life is a continual experience. We see the Internet as being an incredible amplifier to the experience of life for all of us. It can help humanity come together to explode in knowledge exploration and discussion. It is continual enlightenment of new ideas, experiences, and passions


Author Link

 photo ahp banner aspnet-01_zps87l92lcl.png

 

Corporate Address (Location)

ASPHostPortal
170 W 56th Street, Suite 121
New York, NY 10019
United States

Tag cloud

Sign in