By Ugo Lattanzi on Jan. 12th , 2016 in aspnet | comments

With ASP.NET 5 is possible to host your web applications in different ways; of course you can always host your application using IIS (Internet Information Services) and probably it is the best way if you are running your application on top of a Windows OS, but sometimes could be helpful to run test your application also outside of IIS.

For all people who don’t know what Kestrel is (but you should have guessed) let me past here the official definition

Kestrel is a cross-platform web server based on libuv, a cross-platform asynchronous I/O library. Kestrel is open-source, and you can view the Kestrel source on GitHub. Kestrel is a great option to at least include support for in your ASP.NET 5 projects so that your project can be easily run by developers on any of the supported platforms. You add support for Kestrel by including “Kestrel” in your project’s dependencies listed in project.json.

Now that you know what is Kestrel let’s see how to use it.

First of all, when you create a new project from Visual Studio or Yeoman the project is automatically configured to run using Kestrel, in fact into your project.json you should have something like that

Kestrel-001

My code is based on the RC1 but should be the same also if you are running and older or newer version.

The arrows show you two important things:

  1. Kestrel dependency
  2. Web command

The first one is the normal reference you need if you want to run your web application on Kestrel, the second one is the command to run into your project folder (is the same to run dnu web)

Now you have your application ready (I used Web Application template, see here) you have two ways to run it on Kestrel.

From command line run dnu web getting an output like this (maybe you have to run dnu restore if is the first time with your app)

Kestrel-002

or using the play button from Visual Studio

Kestrel-003

That’s pretty easy but is helpful only you want to test your application locally, right now you are not specifying any domain host and you are exposing your application on to schema http and not https. That’s not so good in a real world so, let’ start to see how to do more with Kestrel.

Because we want to run our application on https, first of all we have to buy a certificate. For demo purpose I’ve create one myself (so is not trusted) but is ok for now. Below the steps to create your own self signed certificate

Kestrel-004

Kestrel-005

Kestrel-006

Now your test certificate is ready, let’s add the Kestrel.Https dependency to our project. To do that let’s open the project.json and add Microsoft.AspNet.Server.Kestrel.Https

Now it’s time to configure the certificate into our Startup class like this:

public void Configure(IApplicationBuilder app, 
                                    IHostingEnvironment env,
                                    IApplicationEnvironment appEnv,
                                    ILoggerFactory loggerFactory)

    var certFile = applicationEnvironment.ApplicationBasePath + "\\democertificate.pfx";
    var signingCertificate = new X509Certificate2(certFile, "democertificate.io");

    app.UseKestrelHttps(signingCertificate);

    //...... your code
}

As you can see the code is pretty simple, is enough to create the X509Certificate2 class and call the specific method UseKestrelHttps.

Note: if you are running the RC1 of Microsoft.AspNet.Server.Kestrel.Https you have a problem with the schema. That because it’s a bit buggy as you can see here (https://github.com/aspnet/KestrelHttpServer/issues/551). That is fixed with the RC2 (not released yet) but, in the meanwhile, you can use a simple workaround like this

private static RequestDelegate ChangeContextToHttps(RequestDelegate next)
{
    return async context =>
    {
        context.Request.Scheme = "https";
        await next(context);
    };
}

public void Configure(IApplicationBuilder app, 
                                    IHostingEnvironment env,
                                    IApplicationEnvironment appEnv,
                                    ILoggerFactory loggerFactory)

    var certFile = applicationEnvironment.ApplicationBasePath + "\\democertificate.pfx";
    var signingCertificate = new X509Certificate2(certFile, "democertificate.io");

    app.Use(ChangeContextToHttps);
    app.UseKestrelHttps(signingCertificate);

    //...... your code
}

Finally we have to specify out custom domain and the https protocol to Kestrel. To do this is enough to add a json file into the root of the project named hosting.json and put this code into it

{
  "server": "Microsoft.AspNet.Server.Kestrel",
  "server.urls": "http://localhost:5000;https://localhost:5001"
}

As you can see you can specify more than one url and, if you have mapped the DNS, you can also replace localhost with your domain (i.e. http://tostring.it).

Finally the result

Kestrel-006

Stay tuned!

By Ugo Lattanzi on Nov. 23rd , 2015 in various | comments

In our company we use Slack as communication tool (probably since it was released years ago) for about everything. It is becoming a really important tool because our teams are located throughout Europe with different timezones so, a good communication tools is mandatory. It means also that the client is always open on our computers, phones and tablets.

We use it in different ways, to talk one to one, to share funny things, or for projects. Usually for a project we have more than a single private channel, because there are different teams for the project and because we use a channel as alerts application.

Here is an example about one of our customers:

  • bmw-ux (UX and Art stuff)
  • bmw-dev (dev, quality assurance, github integration, trello and other tech stuff)
  • bmw-alerts (alerts by the application)

The last channel is the most important one for this post, because we use it to log information when something goes wrong into the application. Before to see how to use it, let me explain our logging workflow.

The application is built partially on .NET hosted on Azure and we use Serilog as logging framework. It's a really good logging framework and it offers several appenders. We store all logs into ElastichSearch and use Kibana as dashboard to see the log, reports and other cool stuff. The output of our dashbord looks more or less like this:

Kibana-Dashboard

The usage is really simple


ILogger log = new LoggerConfiguration()
    .Enrich.With<ExceptionDataEnricher>()
    .Enrich.With<MachineNameEnricher>()
    .Enrich.With<HttpRequestClientHostIpEnricher>()
    .Enrich.With<HttpRequestUrlEnricher>()
    .Enrich.With<HttpRequestUrlReferrerEnricher>()
    .Enrich.With<UserNameEnricher>()
    .Enrich.With<ThreadIdEnricher>()
    .Enrich.With(
                        new EnvironmentIdEnricher("Production"), 
                        new ApplicationIdEnricher(applicationName))

    .MinimumLevel.Error()
    .WriteTo.Email(new EmailConnectionInfo
    {
        EmailSubject = $"[BMW {applicationName}] Something went wrong",
        EnableSsl = smtpConfig.EnableSsl,
        FromEmail = smtpConfig.From,
        NetworkCredentials = new NetworkCredential(smtpConfig.Username, smtpConfig.Password),
        Port = smtpConfig.Port,
        ToEmail = emailConfiguration.SupportEmail,
        MailServer = smtpConfig.Host,
    })
    //https://github.com/serilog/serilog/wiki/Configuration-Basics
    .WriteTo.Logger(lc => lc
                                .Filter.ByExcluding(le => le.RenderMessage().StartsWith("....myStuff")
                                .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(elasticSearchConfiguration.Url))
    )
    .CreateLogger();

As you can see in the code above, we use also to send the error via email. For me it's not the best way to have an important notification. All people could write you an email and you need a notification everytime you get an email so it's difficult to enphatize a log message in tons of emails. For this reason we chose to use a private channel on Slack to log important errors. I think it's pretty easy to do that with any logger, but it is for sure using Serilog.

The first thing to do is to configure Slack integration services:

Image 1: Slack-001 Image 2: Slack-002 Image 3: Slack-003 Image 4: Slack-004

Now save and create your Serilog Slack Sink

namespace Gaia.Bmw.Logging.Serilog.Sinks
{
    using System.Net.Http;
    using Enrichers;
    using global::Serilog.Core;
    using global::Serilog.Events;

    public class SlackSink : ILogEventSink
    {
        private const string SlackWebhookUrl = "here the url you copied from the image 2";
        private readonly string applicationId;
        private readonly string environmentType;


        public void Emit(LogEvent logEvent)
        {
            this.applicationId = "";            //read the application identifier from your configuration
            this.environmentType = "";      //read the environment type from your configuration

            string color;

            switch (logEvent.Level)
            {
                case LogEventLevel.Error:
                case LogEventLevel.Fatal:
                    color = "danger";
                    break;
                case LogEventLevel.Warning:
                    color = "warning";
                    break;
                default:
                    color = "good";
                    break;
            }

            //handlse some scenarios, this probably is not needed in your application
            var title = logEvent.Exception != null
                                ? logEvent.RenderMessage()
                                : "New error occured";

            var exceptinon = logEvent.Exception != null
                                ? logEvent.Exception.ToString()
                                : logEvent.RenderMessage();

            var obj = new
            {
                attachments = new[]
                {
                    new
                    {
                        fallback = $"[{this.applicationId}] [{this.environmentType}] An error occurred.",
                        color = color,
                        title = title,
                        text = exceptinon,
                        fields = new[]
                        {
                            new
                            {
                                title = "Project",
                                value = this.applicationId,
                                @short = "true"
                            },
                            new
                            {
                                title = "Environment",
                                value = this.environmentType,
                                @short = "true"
                            }
                        }
                    }
                }
            };

            HttpClient client = new HttpClient();

            client.PostAsJsonAsync(SlackWebhookUrl, obj).Wait();
        }
    }
}

Now that you have everything ready, it's time to register the Sink into Serilog so


.MinimumLevel.Error()
.WriteTo.Sink<SlackSink>()
.CreateLogger();

The output on slack should be like this:

Slack-005

If you want to customize the output message take a look here Enjoy

By Ugo Lattanzi on June 8th , 2015 in various | comments

Today we announced (here) by the official channel some important news about the next Web European Conference

That will be a really AMAZING conference and we had several news for you and for all the attendees.

The previous conference was sold out in 40 minutes for 170 available seats, but now we have more seats so everything should go in the right way for all of you but, if you want to be the first to know about the conference, and to have the possibility to pre-register before the official registration opens, go to our website http://webnextconf.eu/ and subscribe to the mailing list. First July the registration will be free for all but, few hours early, we'll send the registration link to all people who subscribe our newsletter.

As for the previous edition, the conference will be free. That's really important and it's the difficult part of the organization. Is not easy to find the money for speakers, rooms, other stuff and keep the tickets free, for this reason your support is more important than ever.

During the registration you can choose if you wanna come for free, if you want the lunch (around 10€), the T-Shirt (€10) and if you want to make a donation (as you wish). We'll use the donation for the organization, speakers, stickers and other stuff like that.

The conference will be in Milan, University of Milano-Bicocca so, if you think you wanna come, it's time to book your hotel. That's important because there is the Expo fair in Milan, so lot of hotels are fully booked, don't wait!

All the information about the location is available on the conference web site here

Finally, I'm very happy to announce two important speakers that will be here in Milan The Great Scott Hanselman and the fabulous Dino Esposito who will talk about ASP.NET vNext and "Extending RWD with Lightweight Client-side Device Detection".

So far we received almost 50 proposals from 20+ different speakers, but to get even more speeches to choose from, we've decided to keep the call for presenters open till the end of June: if you haven't done it yet and you want have the chance to be in the "speakers room" with Scott, go on our Github account, fork the c4p repository, add your proposal and submit a pull request.

Is that cool enough? Yeah! But the surprices are not over, other cool speakers could come, so stay tuned.

By Ugo Lattanzi on April 23rd , 2015 in various | comments

In the previous post (you can read it here) I wrote about how cool is Redis as cache server and I showed the basic steps to run Redis on premise or on Microsoft Azure if you prefer.

In this post I wanna introduce an small package available on NuGet that complete one of the best library actually available for Redis in a .NET environement.

The package is StackExchange.Redis.Extensions and, as you can imagine from the name, it offers a set of useful helper.

What can we do easily with StackExchange.Redis.Extensions?

In the previous post I wrote that you have to serialize and deserialize a class if you wanna store it into Redis because the library stores a byte[] and the value could be sent via network. Using this library you don't have to worry about that, it does that for you. Right now it can use three different serialization libraries :

  • JSON.Net by NewtonSoft NuGet Status
  • Jil NuGet Status
  • Message Pack CLI NuGet Status

If you need to use another serializazion library you can easily do it by creating an implementation of ISerialize. Of course in this case a Pull Request is welcome

In the example below I'm going to use JSON.Net but the code is the same for the other librarys, just the Nuget Package changes.

First step is to install it on our project so:

PM> Install-Package StackExchange.Redis.Extensions.Newtonsoft

It contains all you need to use Redis, so you don't have to add StackExchange.Redis because it has the right dependency to it.

Now that we are ready, it's enough to create our ICacheHelper instance

var serializer = new NewtonsoftSerializer();
var cacheClient = new StackExchangeRedisCacheClient(serializer);

The constructor of StackExchangeRedisCacheClienthas different overloads offering you the opportunity to specify your custom serializer, database, connection string or, if you have it, your instance of ConnectionMultiplex.

If you use the code above is enough the add the following code to your configuration file replacing the right values (host, port, ssl and so on):

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="redisCacheClient"
               type="StackExchange.Redis.Extensions.Core.Configuration.RedisCachingSectionHandler, StackExchange.Redis.Extensions.Core" />
    </configSections>

    <redisCacheClient allowAdmin="true" ssl="false" connectTimeout="5000" database="0">
        <hosts>
            <add host="127.0.0.1" cachePort="6379"/>
        </hosts>
    </redisCacheClient>
</configuration>

If you use a dependency injection framework, probably it's better to register it as singleton

From now we have a set of useful methods for the following scenarios:

How can I store a complex object into Redis?

var user = new User()
{
    Firstname = "Ugo",
    Lastname = "Lattanzi",
    Twitter = "@imperugo"
    Blog = "http://tostring.it"
}

bool added = myCacheClient.Add("my cache key", user, DateTimeOffset.Now.AddMinutes(10));

How can I retrieve an object into Redis?

var cachedUser = cacheClient.Get<User>("my cache key");

How can I retrieve multiple objects with single roundtrip?

That's one of my favorite features because It's very helpful in case you have to retrieve several objects in the same time.

var cachedUsers = myCacheClient.GetAll<User>(new {"key1","key2","key3"});

How can I add multiple objects with single roundtrip?

IList<User> values = new List<User>();

var user1 = new User()
{
    Firstname = "Ugo",
    Lastname = "Lattanzi",
    Twitter = "@imperugo"
    Blog = "http://tostring.it"
}

var user2 = new User()
{
    Firstname = "Simone",
    Lastname = "Chiaretta",
    Twitter = "@simonech"
    Blog = "http://codeclimber.net.nz/"
}

var user3 = new User()
{
    Firstname = "Matteo",
    Lastname = "Pagani",
    Twitter = "@qmatteoq"
    Blog = "http://qmatteoq.com/"
}

values.Add(user1);
values.Add(user2);
values.Add(user3);

bool added = sut.AddAll(values);

Can I search keys into Redis?

Yes that's possible using a specific pattern. If you want to search all keys that start with myCacheKey:

var keys = myCacheClient.SearchKeys("myCacheKey*");

If you want to search all keys that contain with myCacheKey:

var keys = myCacheClient.SearchKeys("*myCacheKey*");

If you want to search all keys that end with myCacheKey:

var keys = myCacheClient.SearchKeys("*myCacheKey");

Can I use a Redis method directly from ICacheClient without adding another dependency to my class?

Of course you can. ICacheClient exposes a readonly property named Database that is the implementation of IDatabase by StackExchange.Redis

How can I get server information?

ICacheClient has a method GetInfo and GetInfoAsync for that:

var info = myCacheClient.GetInfo();

That's what the library does right now and I've to say thanks to ziyasal, ppanyukov and rajasekarshanmugam for the contribution.

The project is available on Github here

By Ugo Lattanzi on Mar. 16th , 2015 in Owin | comments

I'm very happy to announce that, from today, my first book is available here thanks to Syncfusion that is a popular company among developers for their great suites of controls. The ebook is focused on OWIN (Open Web Server Interface for .NET specification) and it's co-written with my friend Simone Chiaretta who is organizing with me the 2° Web European Conference.

It's a free ebook and, in 110 pages, it covers the most important things you need to know about OWIN from the basic stuff, like "What is OWIN" and "The Middleware", to more complex stuff like "Authentication using social networks" like Facebook, Twitter and Google with ASP.NET Identity and ASP.NET MVC.

Here is the TOC of the book:

  • OWIN
  • Katana
  • Using Katana with Other Web Frameworks
  • Building Custom Middleware
  • Authentication with Katana
  • Appendix

The book is distributed by Syncfusion for free, you just have to register and then you’ll be able to download it both in PDF and Kindle format. Of course if you have feedbacks or you find something that is not clear, that sounds strange or whatever, please don't hesistate to contact me

Owin Succinctly