A Step-by-Step Guide to Migrating a Project from ASP.NET MVC to ASP.NET Core

app.UseMvc(routes =>  routes.MapRoute("areaRoute", "space:exists///"); routes.MapRoute( identify: "default", template: "//"); );
When doing it, the folder with the identify House with the Admin folder within, will have to be within the app root. Now the characteristic

[Area("Admin")] [Route("admin")].

can be used to attach the controller with this space.

It stays most effective to create perspectives for the entire movements described within the controller.

public elegance AdminController : Controller


IFormCollection will have to now not be handed to the controllers since on this case, asp.internet server validation is disabled – MVC is suppressing additional validation if the IFormCollection is located to be now not null. To unravel the issue, this assets could be added to the type, this may increasingly save you us from passing at once to the controller means.

This rule works provided that a type is to be had, if there’s no type, there can be no validation.

Kid houses are not robotically validated and will have to be specified manually.

Step 6. Migrate HTTP handlers and HttpModules to Middleware

HTTP handlers and HTTP modules are if truth be told very an identical to the concept that of Middleware in ASP.NET Core, however in contrast to modules, the middleware order is in line with the order by which they’re inserted into the request pipeline. The order of modules is principally in line with the occasions of application lifestyles cycle. The order of middleware for responses is reverse to the order for requests, whilst the order of modules for requests and responses is identical. Realizing this, you’ll continue with the replace.

What will have to be up to date:

  • Migration of modules for Middleware (AuthenticationMiddleware, CultureMiddleware, and so forth.)
  • Handlers to Middleware
  • Use of latest middleware

Authentication in nopCommerce does now not use a integrated authentication components; for this function, AuthenticationMiddleware advanced in keeping with the brand new ASP.NET Core construction is used.

public elegance AuthenticationMiddleware
{ personal readonly RequestDelegate _next; public AuthenticationMiddleware(IAuthenticationSchemeProvider schemes, RequestDelegate subsequent)  Schemes = schemes ?? throw new ArgumentNullException(nameof(schemes)); _next = subsequent ?? throw new ArgumentNullException(nameof(subsequent));  public IAuthenticationSchemeProvider Schemes  public async Process Invoke(HttpContext context) 

ASP.NET supplies a lot of integrated middleware that you’ll use on your application, however the developer too can create his personal middleware and upload it to HTTP request pipeline.

To simplify this procedure, we added a particular interface to nopCommerce, and now it’s sufficient to simply create a elegance that implements it.

public interface INopStartup
 /// <abstract> /// Upload and configure any of the middleware /// </abstract> /// <param identify="products and services">Selection of provider descriptors</param> /// <param identify="configuration">Configuration of the application</param> void ConfigureServices(IServiceCollection products and services, IConfiguration configuration); /// <abstract> /// Configure the the use of of added middleware /// </abstract> /// <param identify="application">Builder for configuring an application's request pipeline</param> void Configure(IApplicationBuilder application); /// <abstract> /// Will get order of this startup configuration implementation /// </abstract> int Order 

Right here you’ll upload and configure your middleware:

/// <abstract>
/// Represents object for the configuring authentication middleware on application startup
/// </abstract>
public elegance AuthenticationStartup : INopStartup

Step 7. The use of integrated DI

Dependency injection is one of the most important options when designing an app in ASP.NET Core. You’ll increase loosely coupled programs which can be extra testable, modular and as a end result extra maintainable. This used to be made imaginable by way of following the main of dependency inversion.

To inject dependencies, we used IoC (Inversion of Keep watch over) boxes. In ASP.NET Core, such a container is represented by way of the IServiceProvider interface. Services and products are put in within the app within the Startup.ConfigureServices() means.

Any registered provider will also be configured with three scopes:

  • brief
  • scoped
  • singleton

products and services.AddDbContext<ApplicationDbContext>(choices =>
products and services.AddSingleton<Isingleton,MySingleton>();

Step 8. The use of WebAPI challenge compatibility shells (Shim)

  • Including ApiController sort;
  • Enabling internet API taste type binding;
  • Extending type binding in order that controller movements can settle for HttpRequestMessage sort parameters;
  • Including message formatters enabling movements to go back result of HttpResponseMessage sort.

products and services.AddMvc().AddWebApiConventions(); routes.MapWebApiRoute(identify: "DefaultApi", template: "api/controller/"

Step 9. Porting Application Configuration

Some settings had been prior to now stored within the internet.config report. Now we use a new means in line with the key-value pairs set by way of configuration suppliers. That is the beneficial means in ASP.NET Core, and we use the appsettings.json report.
You’ll additionally use the NuGet bundle


if for some explanation why you need to proceed the use of *.config. On this case, the app can not run on Unix platforms, however on IIS most effective.

Step 10. Porting static content material to wwwroot

To serve static content material, specify to internet host the content material root of the present listing. The default is wwwroot. You’ll configure your folder for storing static information by way of putting in place middleware.

Step 11. Porting EntityFramework to EF Core

If the challenge makes use of some explicit options of Entity Framework 6, which can be now not supported in EF Core, it is smart to run the application at the NET Framework. Even though on this case, we can have to reject the multi-platform characteristic, and the application will run on Home windows and IIS most effective. 

Underneath are the primary adjustments to be thought to be:

  • Machine.Information.Entity namespace is changed by way of Microsoft.EntityFrameworkCore;
  • The signature of the DbContext constructor has been modified. Now you will have to inject DbContextOptions;
  • HasDatabaseGeneratedOption(DatabaseGeneratedOption.None) means is changed by way of ValueGeneratedNever();
  • WillCascadeOnDelete(false) means is changed by way of OnDelete (DeleteBehavior.Prohibit);
  • OnModelCreating(DbModelBuilder modelBuilder) means is changed by way of OnModelCreating(ModelBuilder modelBuilder);
  • HasOptional means is not to be had;
  • Object configuration is modified, now OnModelCreating is the use of since EntityTypeConfiguration is not to be had;
  • ComplexType characteristic is not to be had;
  • IDbSet interface is changed by way of DbSet;
  • ComplexType – advanced sort fortify seemed in EF Core 2 with the Owned Entity sort, and tables with out Number one Key with QueryType in EF Core 2.1;
  • Exterior keys in EF Core generate shadow houses the use of the [Entity]Identification template, in contrast to EF6, that makes use of the [Entity]_Id template. Due to this fact, upload exterior keys as a common assets to the entity first;
  • To fortify DI for DbContext, configure your DbContex in ConfigureServices.

/// <abstract>
/// Sign up base object context
/// </abstract>
/// <param identify="products and services">Selection of provider descriptors</param>
public static void AddNopObjectContext(this IServiceCollection products and services)
 products and services.AddDbContextPool<NopObjectContext>(optionsBuilder => );
 /// <abstract>
/// SQL Server explicit extension means for Microsoft.EntityFrameworkCore.DbContextOptionsBuilder
/// </abstract>
/// <param identify="optionsBuilder">Database context choices builder</param>
/// <param identify="products and services">Selection of provider descriptors</param>
public static void UseSqlServerWithLazyLoading(this DbContextOptionsBuilder optionsBuilder, IServiceCollection products and services)

To ensure that EF Core generates a an identical database construction as Entity Framework when migrating, use the  SQL Evaluate software.

Step 12. Putting off all HttpContext references and changing out of date categories and converting the namespace

All over the challenge migration, you are going to to find that a sufficiently huge collection of categories had been renamed or moved, and now you will have to agree to the brand new necessities. Here’s a checklist of the primary adjustments it’s possible you’ll come upon:

  • HttpPostedFileBase 🡪 FormFile
  • Get right of entry to HttpContext can now be accessed by way of IHttpContextAccessor
  • HtmlHelper 🡪 HtmlHelper
  • ActionResult 🡪 ActionResult
  • HttpUtility 🡪 WebUtility
  • ISession as an alternative of HttpSessionStateBase out there from HttpContext.Consultation. from Microsoft.AspNetCore.Http
  • Request.Cookies returns IRequestCookieCollection: IEnumerable <KeyValuePair<string, string> >, then as an alternative of HttpCookie we use KeyValuePair <string, string> from Microsoft.AspNetCore.Http

Namespace alternative:

  • SelectList 🡪 Microsoft.AspNetCore.Mvc.Rendering
  • UrlHelper 🡪 WebUtitlity
  • MimeMapping 🡪 FileExtensionContentTypeProvider
  • MvcHtmlString 🡪 IHtmlString and HtmlString
  • ModelState, ModelStateDictionary, ModelError 🡪 Microsoft.AspNetCore.Mvc.ModelBinding
  • FormCollection 🡪 IFormCollection
  • Request.Url.Scheme 🡪 this.Url.ActionContext.HttpContext.Request.Scheme


  • MvcHtmlString.IsNullOrEmpty(IHtmlString) 🡪 String.IsNullOrEmpty(variable.ToHtmlString())
  • [ValidateInput (false)] – does now not exist anymore and is not wanted
  • HttpUnauthorizedResult 🡪 UnauthorizedResult
  • [AllowHtml] – directive does now not exist anymore and is not wanted
  • TagBuilder.SetInnerText means is changed by way of InnerHtml.AppendHtml
  • JsonRequestBehavior.AllowGet when returning Json is not wanted
  • HttpUtility.JavaScriptStringEncode. JavaScriptEncoder.Default.Encode
  • Request.RawUrl. Request.Trail + Request.QueryString will have to be one after the other hooked up
  • AllowHtmlAttribute – elegance not exists
  • XmlDownloadResult – now you’ll use simply go back Report(Encoding.UTF8.GetBytes (xml), “application / xml”, “filename.xml”);
  •  [ValidateInput(false)] – directive does now not exist anymore and is not wanted

Step 13. Authentication and authorization replace

As used to be already discussed above, nopCommerce challenge does now not contain the integrated authentication components, it’s carried out in a separate middleware layer.

Alternatively, ASP.NET Core has its personal components for credentials offering. You’ll view the documentation to learn about them in main points.
As for information coverage, we not use MachineKey. As a substitute, we use the integrated information coverage characteristic. By means of default, keys are generated when the application begins. As the information garage will also be:
  • Report components – report system-based keystore
  • Azure Garage – information coverage keys in Azure BLOB object garage
  • Redis – information coverage keys within the Redis cache
  • Registry – used if the application does now not have get right of entry to to the report components
  • EF Core – keys are saved within the database
If the integrated suppliers don’t seem to be appropriate, you’ll specify your personal key garage supplier by way of making a customized IXmlRepository.

Step 14. JS/CSS replace

The best way of the use of static assets has modified, now they will have to all be saved within the root folder of the challenge wwwroot, except different settings are made.

When the use of javascript integrated blocks, we propose transferring them to the tip of the web page. Simply use the asp-location = “Footer” characteristic to your <script> tags. The similar rule applies to js information.

Use the BundlerMinifier extension as a alternative for Machine.Internet.Optimization – this may increasingly allow bundling and minification. JavaScript and CSS whilst development the challenge (view the documentation).

Step 15. Porting perspectives

Initially, Kid Movements are not used, as an alternative, ASP.NET Core suggests the use of a new high-performance software – ViewComponents referred to as asynchronously.

How to get a string from ViewComponent:

/// <abstract>
/// Render element to string
/// </abstract>
/// <param identify="componentName">Part identify</param>
/// <param identify="arguments">Arguments</param>
/// <returns>End result</returns>
secure digital string RenderViewComponentToString(string componentName, object arguments = null)

Word that there’s no want to use HtmlHelper anymore, ASP.NET Core comprises many auxiliary integrated Tag Helpers. When the application is working, the Razor engine handles them at the server and in the long run converts to usual html components.

This makes application building a good deal more uncomplicated. And naturally, you’ll enforce your personal tag helpers.

We began the use of dependency injection in perspectives as an alternative of enabling settings and products and services the use of EngineContext.

So, the details on porting perspectives are as follows:

  • Convert Perspectives/internet.config to Perspectives/_ViewImports.cshtml – to import namespaces and inject dependencies. This report does now not fortify different Razor options, reminiscent of serve as and phase definitions
  • Convert namespaces.upload to @the use of
  • Porting any settings to the primary application configuration
  • Scripts.Render and Types.Render don’t exist. Change with hyperlinks to output information of libman or BundlerMinifier


The method of migrating a huge internet application is a very time-consuming process which, as a rule, can’t be performed with out the pitfalls. We deliberate to migrate to a new framework once its first solid model used to be launched however weren’t ready to make it immediately, as there have been some essential options that had now not been transferred to .NET Core, particularly, the ones comparable to EntityFramework.

Due to this fact, we had first to make our unlock the use of a blended means – the .NET Core structure with the .NET Framework dependencies, which in itself is a distinctive answer.

Being first isn’t simple, however we’re positive we’ve made the appropriate selection, and our large neighborhood supported us on this.

We had been ready to totally adapt our challenge after the discharge of .NET Core 2.1, having by way of that point a solid answer already running at the new structure. It remained most effective to substitute some applications and rewrite the paintings with EF Core.

Thus, it took us a number of months and two launched variations to totally migrate to the brand new framework. 

We will say with self belief that we’re the first huge challenge to perform such a migration. On this information, we attempted to put in combination all the migration procedure in a structured shape and describe quite a lot of bottlenecks in order that different builders may depend on this subject matter and practice the roadmap when fixing the similar process.
(Visited 6 times, 1 visits today)

Leave a Reply