Sorted By: Tag (asp-net-vnext)

How Azure Web Apps Hosts an ASP.NET 5 Application

ASP.NET 5 application has totally a different directory structure when you try to publish it and it wasn't clear for me how Azure Web Apps is actually able to host an ASP.NET 5 application. If you are confused on this as well, the answer is here.
2015-04-12 10:13
Tugberk Ugurlu


I want to write this quick post because figuring out how an ASP.NET 5 application is hosted under Azure Web Apps was a big question for me. Some information is already there on this topic but the concept wasn’t crystal clear because when you look at the packed version of an ASP.NET 5 web application, it has the following structure on disk:

image

It will even get more interesting when you look inside the wwwroot folder:

image

We have the static files, bin folder which only contains AspNet.Loader.dll inside it and a web.config file. The most interesting bit here is the information inside the web.config file and this information will be read by Helios:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="bootstrapper-version" value="1.0.0-beta4-11526" />
    <add key="runtime-path" value="..\approot\packages" />
    <add key="dnx-version" value="" />
    <add key="dnx-clr" value="" />
    <add key="dnx-app-base" value="..\approot\src\ConfyConf.Client.Web" />
  </appSettings>
</configuration>

web.config file gives us enough evidence that the wwwroot is the directory that we need to point IIS to and then Helios will read these application settings information to figure out where the application actually is, where the dependencies and packages are, etc.. Let’s deploy the application using Visual Studio Publish feature. I created a brand new Azure Web App on the fly and hit publish:

image

When the deployment is completed, the web site is immediately up:

image

Let’s look at how the directory structure look like after the deployment:

image

Two interesting bits here are approot and wwwroot folders. The question here is that how Azure Web App knew to look into wwwroot folder. It was actually dead simple but it wasn’t obvious at the first glance. Before showing the answer, let’s have a look what IIS Express does to host an ASP.NET 5 application which will give us an hint on the answer.

I fired up the application through the Visual Studio to get IIS Express host my application. After the application is up, I dug into Task Manager to get the command line arguments for IIS Express:

iisexpress.exe    10736    Running    Tugberk    00     33,804 K    33    "C:\Program Files (x86)\IIS Express\iisexpress.exe"  /config:"C:\Users\Tugberk\Documents\IISExpress\config\applicationhost.config"  /site:"WebApplication10" /apppool:"Clr4IntegratedAppPool"    IIS Express Worker Process

This points us to applicationhost.config file and WebApplication10 site inside it. When you look at the site node for WebApplication10, you will see that some of the magic is actually happening there:

<site name="WebApplication10" id="77">
    <application path="/" applicationPool="Clr4IntegratedAppPool">
        <virtualDirectory path="/" physicalPath="D:\apps\WebApplication10\src\WebApplication10\wwwroot" />
    </application>
    <bindings>
        <binding protocol="http" bindingInformation="*:47112:localhost" />
    </bindings>
</site>

wwwroot is pointed as a virtual directory for the web application here for the root path. So, is this information helping us to see how Azure Web App is hosting our app? Absolutely! It gives us the information that something similar should be configured on Azure Web Apps side that it sees the wwwroot folder as the root. If you navigate to Configure section for your Azure Web App and scroll down to the bottom, you will see the virtual directory configuration there.

azure-aspnet5-virtual-directory

Clever! My guess is that this configuration was put there when I was publishing the Web Application through web deploy inside the Visual Studio. Digging into Web Publish Activity output could give us more information about when exactly this configuration is set.

Exciting Things About ASP.NET vNext Series: Middlewares and Per Request Dependency Injection

From the very first day of ASP.NET vNext, per request dependencies feature is a first class citizen inside the pipeline. In this post, I'd like to show you how you can use this feature inside your middlewares.
2014-11-09 21:20
Tugberk Ugurlu


Web development experience with .NET has never seen a drastic change like this since its birth day. Yes, I’m talking about ASP.NET vNext :) I have been putting my toes into this water for a while now and a few weeks ago, I started a new blog post series about ASP.NET vNext. To be more specific, I’m planning on writing about the things I am actually excited about this new cloud optimized (TM) runtime. Those things could be anything which will come from ASP.NET GitHub account: things I like about the development process, Visual Studio tooling experience for ASP.NET vNext, bowels of this new runtime, tiny little things about the frameworks like MVC, Identity, Entity Framework.

Today,  I would like to show you one of my favorite features in ASP.NET vNext: per-request dependencies.

BIG ASS CAUTION! At the time of this writing, I am using KRE 1.0.0-beta2-10679 version. As things are moving really fast in this new world, it’s very likely that the things explained here will have been changed as you read this post. So, be aware of this and try to explore the things that are changed to figure out what are the corresponding new things.

Also, inside this post I am referencing a lot of things from ASP.NET GitHub repositories. In order to be sure that the links won’t break in the future, I’m actually referring them by getting permanent links to the files on GitHub. So, these links are actually referring the files from the latest commit at the time of this writing and they have a potential to be changed, too. Read the "Getting permanent links to files" post to figure what this actually is.

If you follow my blog, you probably know that I have written about OWIN and dependency injection before. I also have a little library called DotNetDoodle.Owin.Dependencies which acts as an IoC container adapter into OWIN pipeline. One of the basic ideas with that library is to be able to reach out to a service provider and get required services inside your middleware. Agree or disagree, you will sometimes need external dependency inside your middleware :) and some of those dependencies will need to be constructed per each request separately and disposed at the end of that request. This is a very common approach and nearly all .NET IoC containers has a concept of per-request lifetime for ASP.NET MVC, ASP.NET Web API and possibly for other web frameworks like FubuMVC

From the very first day of ASP.NET vNext, per request dependencies feature is a first class citizen inside the pipeline. There are a few ways to work with per request dependencies and I’ll show you two of the ways that you can take advantage of inside your middleware.

Basics

For you ASP.NET vNext web application, you would register your services using one of the overloads of UseServices extension method on IApplicationBuilder. Using this extension method, you are registering your services and adding the ContainerMiddlware into the middleware pipeline. ContainerMiddlware is responsible for creating you a dependency scope behind the scenes and any dependency you register using the AddScoped method (in other words, any dependency which is marked with LifecycleKind.Scoped) on the IServiceCollection implementation will end up being a per-request dependency (of course it depends how you use it). The following code is a sample of how you would register your dependencies inside your Startup class:

public void Configure(IApplicationBuilder app)
{
    app.UseServices(services =>
    {
        services.AddScoped<IFarticusRepository, InMemoryFarticusRepository>();
        services.AddTransient<IConfigureOptions<FarticusOptions>, FarticusOptionsSetup>();
    });

    app.UseMiddleware<FarticusMiddleware>();
}

The way you reach out to per-request dependencies also vary and we will go through this topic in a few words later but for now, we should know that request dependencies are hanging off of HttpContext.RequestServices property.

Per-request Dependencies Inside a Middleware (Wrong Way)

Inside the above dependency registration sample code snippet, I also registered FarticusMiddleware which hijacks all the requests coming to the web server and well..., farts :) FarticusMiddleware is actually very ignorant and it doesn’t know what to say when it farts. So, it gets the fart message from an external service: an IFarticusRepository implementation. IFarticusRepository implementation can depend on other services to do some I/O to get a random message and those services might be constructed per request lifecycle. So, FarticusMiddleware needs to be aware of this fact and consume the service in this manner. You can see the implementation of this middleware below (trimmed-down version):

public class FarticusMiddleware
{
    private readonly FarticusOptions _options;

    public FarticusMiddleware(
        RequestDelegate next, IOptions<FarticusOptions> options)
    {
        _options = options.Options;
    }

    public async Task Invoke(HttpContext context)
    {
        IFarticusRepository repository = context
            .RequestServices
            .GetService(typeof(IFarticusRepository)) as IFarticusRepository;

        if(repository == null)
        {
            throw new InvalidOperationException(
                "IFarticusRepository is not available.");
        }

        var builder = new StringBuilder();
        builder.Append("<div><strong>Farting...</strong></div>");
        for(int i = 0; i < _options.NumberOfMessages; i++)
        {
            string message = await repository.GetFartMessageAsync();
            builder.AppendFormat("<div>{0}</div>", message);
        }

        context.Response.ContentType = "text/html";
        await context.Response.WriteAsync(builder.ToString());
    }
}

So, look at what we are doing here:

  • We are getting the IOptions<FarticusOptions> implementation through the middleware constructor which is constructed per-pipeline instance which basically means per application lifetime.
  • When the Invoke method is called per each request, we reach out to HttpContext.RequestServices and try to retrieve the IFarticusRepository from there.
  • When we have the IFarticusRepository implementation, we are creating the response message and writing it to the response stream.

The only problem here is that we are being friends with the notorious service locator pattern inside our application code which is pretty bad. Invoke method tries to resolved the dependency itself through the RequestServices property. Imagine that you would like to write unit tests for this code. At that time, you need know about the implementation of the Invoke method here to write unit tests against it because there is no other way for you to know that this method relies on IFarticusRepository.

Per-request Dependencies Inside a Middleware (Correct Way)

I was talking to a few ASP.NET team members if it was possible to inject per-request dependencies into Invoke method of my middleware. A few thoughts, Louis DeJardin sent a pull request to enable this feature in a very simple and easy way. If you register your middleware using the UseMiddleware extension method on IApplicationBuilder, it checks whether you are expecting any other parameters through the Invoke method rather than an HttpContext instance and inject those if you have any. This new behavior allows us to change the above Invoke method with the below one:

public async Task Invoke(HttpContext context, IFarticusRepository repository)
{
    if(repository == null)
    {
        throw new InvalidOperationException("IFarticusRepository is not available.");
    }

    var builder = new StringBuilder();
    builder.Append("<div><strong>Farting...</strong></div>");
    for(int i = 0; i < _options.NumberOfMessages; i++)
    {
        string message = await repository.GetFartMessageAsync();
        builder.AppendFormat("<div>{0}</div>", message);
    }

    context.Response.ContentType = "text/html";
    await context.Response.WriteAsync(builder.ToString());
}

Nice and very clean! It’s now very obvious that the Invoke method relies on IFarticusRepository. You can find the sample application I referred here under my GitHub account. When you run the application and send an HTTP request to localhost:5001, you will see the log which shows you when the instances are created and disposed:

I am still adding new things to this sample and it's possible that the code is changed when you read this post. However, here is latest state of the sample application at the time of this writing.

image

Getting the Client’s IP Address in ASP.NET vNext Web Applications

I was wondering about how to get client’s IP address inside an ASP.NET vNext web application. It’s a little tricky than it should be but I finally figured it out :)
2014-10-30 10:04
Tugberk Ugurlu


I was wondering about how to get client’s IP address inside an ASP.NET vNext web application. It’s a little tricky than it should be but I finally figured it out. So, I decided to write it down here so that anyone else can see how it’s done right now.

BIG ASS CAUTION! At the time of this writing, I am using KRE 1.0.0-beta2-10648 version. As things are moving really fast in this new world, it’s very likely that the things explained here will have been changed as you read this post. So, be aware of this and try to explore the things that are changed to figure out what are the corresponding new things.

Also, inside this post I am referencing a lot of things from ASP.NET GitHub repositories. In order to be sure that the links won’t break in the future, I’m actually referring them by getting permanent links to the files on GitHub. So, these links are actually referring the files from the latest commit at the time of this writing and they have a potential to be changed, too. Read the "Getting permanent links to files" post to figure what this actually is.

First thing to highlight here is "HTTP Features" feature (mouthful, I know :)). It’s a really exciting design if you ask me and basically, the HTTP server underneath your application will implement certain features and your application can work with these implementations. Some of the features that a server might implement can be found inside the Microsoft.AspNet.HttpFeature package. However, it’s not limited to these features only. You watch Chris Ross talking about HTTP Features on Web Camps TV to find out more about this as he gives a nice overview on HTTP Features design.

One of these HTTP features is HTTP connection feature (IHttpConnectionFeature if you want to be more specific). This feature is responsible for giving local and remote connection information for current request and this is where we can get client’s IP Address. You can try to get IHttpConnectionFeature from the HttpContext instance which you get per each request. HttpContext has two methods called GetFeature and one of them accepts a generic parameter. You can use this method to retrieve a specific feature you want to reach out to. The below Startup class shows you how you can get the client’s IP Address through the IHttpConnectionFeature.

using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using System.Threading.Tasks;
using Microsoft.AspNet.HttpFeature;

namespace RemoteIPAddressSample
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app)
        {
            app.Run(async (ctx) =>
            {
                IHttpConnectionFeature connection = ctx.GetFeature<IHttpConnectionFeature>();
                string ipAddress = connection != null
                    ? connection.RemoteIpAddress.ToString()
                    : null;

                await ctx.Response.WriteAsync("IP Address: " + ipAddress);
            });
        }
    }
}

When I hit the HTTP endpoint now, I’ll see my client’s IP address inside the response body:

image

We can even make this look nicer by refactoring this into an extension method.

public static class HttpContextExtensions
{
    public static string GetClientIPAddress(this HttpContext context)
    {
        if(context == null)
        {
            throw new ArgumentNullException("context");
        }

        IHttpConnectionFeature connection = context.GetFeature<IHttpConnectionFeature>();

        return connection != null
            ? connection.RemoteIpAddress.ToString()
            : null;
    }
}

Way better. We can now use this nice looking HttpContext extension instead:

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Run(async (ctx) =>
        {
            await ctx.Response.WriteAsync("IP Address: " + ctx.GetClientIPAddress());
        });
    }
}

One thing to mention here is that the HTTP server which your application is running on top of may choose not to implement this feature. It sounds like a very unreasonable situation as something this fundamental should be there all the time but it’s what it is. So, you should be always careful when reaching out to properties of this feature as you may get null values when you call GetFeature<T>. This rule probably applies most of the HTTP features but I wasn’t able to find any certain information whether there is a check at the very early stages of the pipeline to refuse to use the server if specific features are not implemented by the server. I’ll probably update the post when I find this out.

Building and Running Your ASP.NET vNext Application with Gulp

Wanna see ASP.NET vNext and Gulp working together? You are at the right place :) Let's have look at gulp-aspnet-k, a little plugin that I have created for ASP.NET vNext gulp integration.
2014-10-09 11:28
Tugberk Ugurlu


I love gulp! It has been only a few weeks since I started getting my hands dirty with gulp but it’s ridiculously simple and good. I am actually using gulp with one of my ASP.NET vNext applications to see how they fit together. I am compiling my less files, doing concatenation and minification for scripts/styles files with gulp. It’s also extremely comforting that gulp has file watch capability. For example, I can change my less files during the development and they are being recompiled as I save them:

gulp-watch

As I am working with my ASP.NET vNext application in this project, I found myself jumping between command prompt windows. I imagined for a second that it would be cool to have a gulp plugin for ASP.NET vNext to build and run the application. It would also take advantage of k --watch so that it would restart the host when any code files are changed. Then, I started digging into it and finally, I managed to get gulp-aspnet-k (ASP.NET vNext Gulp Plugin) out :) gulp-aspnet-k is also available on npm and you can install it right from there. Check out the readme for further info about its usage.

This is an insanely simple plugin which wraps kpm and k commands for you. In its simplest form, its usage is as below:

var gulp = require('gulp'),
    aspnetk = require("gulp-aspnet-k");

gulp.task('default', function(cb) {
    return gulp.start('aspnet-run');
});

gulp.task('aspnet-run', aspnetk());

You can find a sample application that uses gulp-aspnet-k plugin in my ASP.NET vNext samples repository: GulpSample. It is also working with gulp watch in peace.

image

Be sure to watch the following short video of mine to see this tiny plugin in action.

ASP.NET vNext with Gulp from Tugberk Ugurlu on Vimeo.

Keep in mind that, currently, this only works on windows :s Also remember that little things matter in your daily life and this thing is one of them :)

Exciting Things About ASP.NET vNext Series: MVC View Components

A few days ago, I started a new blog post series about ASP.NET vNext. Today, I would like to talk about something which is MVC specific and takes one of our pains away: view components :)
2014-10-06 11:46
Tugberk Ugurlu


Web development experience with .NET has never seen a drastic change like this since its birth day. Yes, I’m talking about ASP.NET vNext :) I have been putting my toes into this water for a while now and a few days ago, I started a new blog post series about ASP.NET vNext (with hopes that I will continue this time :)). To be more specific, I’m planning on writing about the things I am actually excited about this new cloud optimized (TM) runtime. Those things could be anything which will come from ASP.NET GitHub account: things I like about the development process, Visual Studio tooling experience for ASP.NET vNext, bowels of this new runtime, tiny little things about the frameworks like MVC, Identity, Entity Framework.

Today, I would like to talk about something which is MVC specific and takes one of our pains away: view components :)

BIG ASS CAUTION! At the time of this writing, I am using KRE 1.0.0-beta1-10494 version. As things are moving really fast in this new world, it’s very likely that the things explained here will have been changed as you read this post. So, be aware of this and try to explore the things that are changed to figure out what are the corresponding new things.

Also, inside this post I am referencing a lot of things from ASP.NET GitHub repositories. In order to be sure that the links won’t break in the future, I’m actually referring them by getting permanent links to the files on GitHub. So, these links are actually referring the files from the latest commit at the time of this writing and they have a potential to be changed, too. Read the "Getting permanent links to files" post to figure what this actually is.

Do you remember ugly, nasty child actions in ASP.NET MVC? I bet you do. Child actions were pain because it’s something so weird that nobody understood at the first glance. They were sitting inside the controller as an action (hence the name) and can be invoked from the view like below:

<div>
    @Html.Action("widget")
</div>

In MVC, if your HTTP request reaches that view and starts rendering, it means (most of the time with the default flow at least) that you already have gone through a controller and an action. Now, we are also invoking a child action here and this basically means that we will go through the pipeline again to pick the necessary controller and action. So, you can no longer tell that only HTTP requests will hit your controller because the child actions are not HTTP requests. They are basically method calls to your action. Not to mention the lack of asynchronous processing support inside the child actions. I’m guessing that a lot of people have seen a deadlock while blocking an asynchronous call inside a child action. In a nutshell, child actions are cumbersome to me.

View Components in ASP.NET vNext

In ASP.NET vNext, all of the ugly behaviors of child actions are gone. To be more accurate, child actions are gone :) Instead, we have something called view components which allows you to render a view and it can be called inside a view. It has the same features of child actions without all the ugliness.

Let me walk you though a scenario where view components might be useful to you. In my website, you can see that I’m listing links to my external profiles at the right side.

image

Possibly, the links are stored in my database and I’m retrieving them by performing an I/O operation. Also, I am viewing these links in all my pages at the right side. This’s a perfect candidate for a view component where you would implement your links retrieval and display logic once (separately), and use it whenever you need it. At its core, your view component is nothing but a class which is derived from the ViewComponent base class. It has a few helper methods on itself like View, Content and Json methods. However, you are not restricted to this. Thanks to new great DI system in K Runtime, we can pass dependencies into view components as well. Let’s build this up.

First of all, I have the following manager class which is responsible for retrieving the profile link list. For the demo purposes, it gets the list from an in-memory collection:

public interface IProfileLinkManager
{
    Task<IEnumerable<ProfileLink>> GetAllAsync();
}

public class ProfileLinkManager : IProfileLinkManager
{
    private static readonly IEnumerable<ProfileLink> _profileLinks = new List<ProfileLink> 
    {
        new ProfileLink { Name = "Twitter", Url = "http://twitter.com/tourismgeek", FaName = "twitter" },
        new ProfileLink { Name = "linkedIn", Url = "http://www.linkedin.com/in/tugberk", FaName = "linkedin" },
        new ProfileLink { Name = "GitHub", Url = "http://github.com/tugberkugurlu", FaName = "github" },
        new ProfileLink { Name = "Stackoverflow", Url = "http://stackoverflow.com/users/463785/tugberk", FaName = "stack-exchange" }
    };

    public Task<IEnumerable<ProfileLink>> GetAllAsync()
    {
        return Task.FromResult<IEnumerable<ProfileLink>>(_profileLinks);
    }
}

public class ProfileLink
{
    public string Name { get; set; }
    public string Url { get; set; }
    public string FaName { get; set; }
}

Inside the Startup.cs file, we need to register the implementation of IProfileLinkManager:

app.UseServices(services => 
{
    services.AddMvc();
    services.AddScoped<IProfileLinkManager, ProfileLinkManager>();
});

View Components and How They Work

We can now create our view component which has a dependency on ProfileLinkManager:

public class ProfileLinksViewComponent : ViewComponent
{
    private readonly IProfileLinkManager _profileLinkManager;

    public ProfileLinksViewComponent(IProfileLinkManager profileLinkManager)
    {
        if (profileLinkManager == null)
        {
            throw new ArgumentNullException("profileLinkManager");
        }

        _profileLinkManager = profileLinkManager;
    }

    public async Task<IViewComponentResult> InvokeAsync()
    {
        var profileLinks = await _profileLinkManager.GetAllAsync();            
        return View(profileLinks);
    }
}

There are couple of things to highlight here. Let’s start with the name of the view component which is very important as we need to know its name so that we can refer to it when we need to process it. The name of the view component can be inferred in two ways:

  • The name can be inferred from the name of the view component class. If the class name has a suffix as "ViewComponent", the view component name will be the class name with "ViewComponent" suffix. If it doesn’t have that suffix, the class name is the view component name as is.
  • You can specifically give it a name by applying the ViewComponentAttribute to the view component class and setting its Name property.

The other thing that is worth mentioning is our ability to inject dependencies into our view component. Any dependency that we have inside the request scope at the time of invocation can be injected into the view component class. Have a look at CreateComponent private method on the DefaultViewComponentInvoker (we will touch on this later) to see how the view component class is activated by default.

The last thing I want to mention is the method of the view component that will be called. By default, you can have two method names here: InvokeAsync or Invoke. As you can guess, InvokeAsync is the one you can use for any type of asynchronous processing. As these two methods are not part of the base class (ViewComponent), we can have as many parameters as we want here. Those parameters will be passed when we are actually invoking the view component inside a view and the registered IViewComponentInvoker (DefaultViewComponentInvoker by default) is responsible for calling the InvokeAsync or Invoke method (if you have both InvokeAsync and Invoke method on your view component, the InvokeAsync will be the one that’s called). From the method, you can return three types (if it’s InvokeAsync, the following types are for the generic parameter of the Task<T> class): IViewComponentResult, string and HtmlString. As you can see, I am using the View method of the ViewComponent base class above which returns IViewComponentResult.

Using the View Components

We covered most of things that we need to know about view components except for how we can actually use them. Using a view component is actually very similar to how we used child actions. We need to work with the Component property inside the view (which is an implementation of IViewComponentHelper). There are a few methods for IViewComponentHelper that we can call. You can see below that I am calling the InvokeAsync by only passing the component name.

<body>
    <div class="col-md-8">
        <hr />
        <div>
            Main section...
        </div>
    </div>
    <div class="col-md-4">
        <hr />
        @await Component.InvokeAsync("ProfileLinks")
    </div>
</body>

And yes, you can await inside the razor view itself :)

InvokeAsync method here also accepts "params object[]" as its second parameter and you can pass the view component parameters there (if there are any). Let’s run the application and see what we are getting:

image

To be able to see this rich error message, you need to pull down the Microsoft.AspNet.Diagnostics package and activate the diagnostic page for your application as I did. Unlike the old ASP.NET world, we don’t get any special feature for free in this world. Remember, pay-for-play model :)

We got an error which is expected:

An unhandled exception occurred while processing the request.

InvalidOperationException: The view 'Components/ProfileLinks/Default' was not found. The following locations were searched: /Views/Home/Components/ProfileLinks/Default.cshtml /Views/Shared/Components/ProfileLinks/Default.cshtml.

Microsoft.AspNet.Mvc.ViewViewComponentResult.FindView(ActionContext context, String viewName)

This’s actually very good that we are getting this error message because it explains what we need to do next. As we didn’t pass any view name, the Default.cshtml the view file is the one our component is looking for. The location of the view needs to be either under the controller that we now rendering (which is Views/Home/ProfileLinks) or the Shared folder (which is Views/Shared/ProfileLinks). Let’s put the view under the Views/Shared/Components/ProfileLinks directory:

@using ViewComponentSample
@model IEnumerable<ProfileLink>

<ul class="profilelink-list">
    @foreach(ProfileLink profileLink in Model)
    {
        <li><a class="btn btn-info" title="@profileLink.Name" href="@profileLink.Url"><i class="fa fa-@(profileLink.FaName) fa-lg"></i></a></li>
    }
</ul>

When we now run the application, we should see that the component is rendered successfully:

image

Nice and shiny! You can find the sample I have gone through here inside the ASP.NET vNext samples repository: ViewComponentSample.

Tags