Click here to Skip to main content
15,885,309 members
Articles / Web Development / ASP.NET / ASP.NETvNext
Article

Working with Service in ASP.NET 5 Application

Rate me:
Please Sign up or sign in to vote.
3.63/5 (6 votes)
11 Jan 2016CPOL3 min read 14.9K   6   1
Working with service in ASP.NET 5 application

Introduction

We know that in ASP.NET 5 the whole framework is rewritten. ASP.NET 5 is not dependent on the old bulky System.Web.dll. That means it’s independent from a particular hosting environment. Now (ASP.NET 5) the framework became very lean and pluggable. So what does it mean? It means, very limited features will ship with ASP.NET 5 and if the user needs more features they are able to easily plug in the framework. By default the MVC framework does not come with ASP.NET 5, if we want to use MVC we have to plug the MVC service on top of ASP.NET 5. The mechanism is very simple, you just have to add a couple of lines in Startup.cs and in the project.json file. If you open any scaffolding Startup.cs file, it will contains two methods and those are ConfigureService and the Configure method.

public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    }
    public void Configure(IApplicationBuilder app)
    {
        app.UseMvc();
    }

We can call AddMvc() and the UseMvc() extension method from ConfigureService and the Configure function to hook MVC in application. In this article, we will dig deeper into the AddMvc() function and discuss the MvcServiceCollectionExtensions class which contains AddMvc() and a few useful methods to hook and configure MVC in ASP.NET 5 applications.

The location of the MvcServiceCollectionExtensions class is in the Microsoft.Framework.DependencyInjection namespace

namespace Microsoft.Framework.DependencyInjection
{
    public static class MvcServiceCollectionExtensions
    {
    }
}

And the class contains following methods.

Image 1

Where AddMvcServices() and ConfigureDefaultServices() are internal and provate simultaneously. If you just open the class in Visual Studio then you may not see those functions by default but it will visible to some de-assembler tool. Now we have seen that we used the AddMvc() function to add MVC services in ASP.NET applications, let’s check the definition to the AddMvc() function see know what really happens when we add the MVC framework in ASP.NET applications. Here is the definition of the AddMvc() function.

public static IServiceCollection AddMvc(this [NotNull] IServiceCollection services)
{
    ConfigureDefaultServices(services);
    AddMvcServices(services);
    return services;
}

We are seeing that, internally, the AddMvc() extension method calls both ConfigureDefaultService() and AddMvcServices() functions which are internal and private function. So let’s check the definition of both functions. Here is the definition of the ConfigureDefaultServices() function.

private static void ConfigureDefaultServices(IServiceCollection services)
{
    OptionsServiceCollectionExtensions.AddOptions(services);
    DataProtectionServiceCollectionExtensions.AddDataProtection(services);
    RoutingServices.AddRouting(services);
    CorsServiceCollectionExtensions.AddCors(services);
    ServiceCollectionExtensions.AddAuthorization(services);
    EncoderServiceCollectionExtensions.AddWebEncoders(services);
    OptionsServiceCollectionExtensions.Configure<RouteOptions>(services, routeOptions => routeOptions.get_ConstraintMap().Add("exists", typeof(KnownRouteValueConstraint)), 0, "");
}

We are seeing that in this function some default services like routing, CORS, Authorization of the MVC Framework are getting added in the application. Those are minimal services to up and run MVC application with limited features. Then it calls the AddServices() function to add other MVC features, too. It contains tons of MVC features.

internal static void AddMvcServices(IServiceCollection services)
{
    ServiceCollectionExtensions.AddTransient<IConfigureOptions<MvcOptions>, MvcOptionsSetup>(services);
    ServiceCollectionExtensions.AddTransient<IConfigureOptions<RazorViewEngineOptions>, RazorViewEngineOptionsSetup>(services);
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IAssemblyProvider, DefaultAssemblyProvider>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<MvcMarkerService, MvcMarkerService>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<ITypeActivatorCache, DefaultTypeActivatorCache>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Scoped(typeof(IScopedInstance<>), typeof(ScopedInstance<>)));
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IControllerTypeProvider, DefaultControllerTypeProvider>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IControllerModelBuilder, DefaultControllerModelBuilder>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IActionModelBuilder, DefaultActionModelBuilder>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IControllerFactory, DefaultControllerFactory>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IControllerActivator, DefaultControllerActivator>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IActionInvokerFactory, ActionInvokerFactory>());
    ServiceCollectionExtensions.AddTransient<IActionConstraintProvider, DefaultActionConstraintProvider>(services);
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IActionSelectorDecisionTreeProvider, ActionSelectorDecisionTreeProvider>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IActionSelector, DefaultActionSelector>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IControllerActionArgumentBinder, DefaultControllerActionArgumentBinder>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IObjectModelValidator>(serviceProvider => new DefaultObjectValidator(ServiceProviderExtensions.GetRequiredService<IOptions<MvcOptions>>(serviceProvider).get_Options().get_ValidationExcludeFilters(), ServiceProviderExtensions.GetRequiredService<IModelMetadataProvider>(serviceProvider))));
    ServiceCollectionExtensions.AddTransient<IActionDescriptorProvider, ControllerActionDescriptorProvider>(services);
    ServiceCollectionExtensions.AddTransient<IActionInvokerProvider, ControllerActionInvokerProvider>(services);
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IActionDescriptorsCollectionProvider, DefaultActionDescriptorsCollectionProvider>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IGlobalFilterProvider, DefaultGlobalFilterProvider>());
    ServiceCollectionExtensions.AddTransient<IFilterProvider, DefaultFilterProvider>(services);
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<FormatFilter, FormatFilter>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<CorsAuthorizationFilter, CorsAuthorizationFilter>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IModelMetadataProvider, DefaultModelMetadataProvider>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<ICompositeMetadataDetailsProvider>(serviceProvider => new DefaultCompositeMetadataDetailsProvider(ServiceProviderExtensions.GetRequiredService<IOptions<MvcOptions>>(serviceProvider).get_Options().get_ModelMetadataDetailsProviders())));
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<JsonOutputFormatter>(serviceProvider => new JsonOutputFormatter(ServiceProviderExtensions.GetRequiredService<IOptions<MvcOptions>>(serviceProvider).get_Options().get_SerializerSettings())));
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Scoped<ICompositeViewEngine, CompositeViewEngine>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IViewLocationCache, DefaultViewLocationCache>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<ICodeTreeCache>(serviceProvider => new DefaultCodeTreeCache(ServiceProviderExtensions.GetRequiredService<IOptions<RazorViewEngineOptions>>(serviceProvider).get_Options().get_FileProvider())));
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IMvcRazorHost, MvcRazorHost>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<ICompilerCache, CompilerCache>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<ICompilationService, RoslynCompilationService>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IRazorCompilationService, RazorCompilationService>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Scoped<IViewStartProvider, ViewStartProvider>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IRazorViewFactory, RazorViewFactory>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IRazorPageActivator, RazorPageActivator>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Scoped<IRazorPageFactory, VirtualPathRazorPageFactory>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IHtmlHelper, HtmlHelper>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient(typeof(IHtmlHelper<>), typeof(HtmlHelper<>)));
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IJsonHelper, JsonHelper>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Scoped<IUrlHelper, UrlHelper>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<ITagHelperActivator, DefaultTagHelperActivator>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IMemoryCache, MemoryCache>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IHtmlGenerator, DefaultHtmlGenerator>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IViewComponentSelector, DefaultViewComponentSelector>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IViewComponentActivator, DefaultViewComponentActivator>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IViewComponentDescriptorCollectionProvider, DefaultViewComponentDescriptorCollectionProvider>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IViewComponentDescriptorProvider, DefaultViewComponentDescriptorProvider>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IViewComponentInvokerFactory, DefaultViewComponentInvokerFactory>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IViewComponentHelper, DefaultViewComponentHelper>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IClaimUidExtractor, DefaultClaimUidExtractor>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<AntiForgery, AntiForgery>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IAntiForgeryAdditionalDataProvider, DefaultAntiForgeryAdditionalDataProvider>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IApiDescriptionGroupCollectionProvider, ApiDescriptionGroupCollectionProvider>());
    ServiceCollectionExtensions.AddTransient<IApiDescriptionProvider, DefaultApiDescriptionProvider>(services);
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Scoped<ITempDataDictionary, TempDataDictionary>());
    ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<ITempDataProvider, SessionStateTempDataProvider>());
}

And the it returns the same instance of IServiceCollection. So now it’s clear that when we call the AddMvc() function are all MVC related features get added in the ASP.NET 5 application. Now the question may come, if we want to alter any MVC feature? The MvcServiceCollectionExtensions Class contains the ConfigureMvc() function where we can alter any MVC features which we have already added in the application. In this example, we will try to alter something in the view engine and will understand the functionality of ConfigureMvc() function. Here is the modified ConfigureServices() function where we are removing view engine by default in the ConfigureMvc() section.

public void ConfigureServices(IServiceCollection services)
{
            services.AddMvc();
            services.ConfigureMvc(f =>
            {
                f.ViewEngines.RemoveAt(0);
            });
}

Which means there is no view engine in the current application to process view. Now let’s perform one HTTP request to a certain controller and we will encounter the below error.

Image 2

I believe and verified all routing stuff, controller and views and in place and the error is due to removing the view engine in the ConfigureMvc() section. Now only alter the existing behavior in which you can register a custom filter and services in same section. Here are a few properties from many where we can alter the default behavior.

Image 3

Conclusion

In this article, we have learned MVC setting and defaults MVC services in ASP.NET 5 application. Those setting and behavior is purely demand oriented and application specific. Please keep in mind that only Adding MVC services will not enable MVC in applications, we need to call the UseMvc() extension method in Configure().

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer DELL International
India India
I am software developer from INDIA. Beside my day to day development work, i like to learn new technologies to update myself. I am passionate blogger and author in various technical community including dotnetfunda.com , c-sharpcorner.com and codeproject. My area of interest is modern web technology in Microsoft stack. Visit to my personal blog here.

http://ctrlcvprogrammer.blogspot.in/

Comments and Discussions

 
QuestionWhat ASP5/MVC6 version is this? Pin
Member 219139020-Jan-16 16:03
Member 219139020-Jan-16 16:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.