.NET Core - MVC

Observations about .NET Core, MVC and converting YetaWF from ASP.NET MVC5 to .NET Core MVC. The new .NET Core has great new features. Getting there from an existing MVC 5 app is HARD!

Incompatibilities Galore

03/11/2017

When we set out to upgrade YetaWF to ASP.NET Core, we envisioned dual support for ASP.NET 4 MVC 5 and ASP.NET Core MVC using the same code base but embracing the new ASP.NET Core and making YetaWF fill in the gaps on ASP.NET 4. Mission accomplished! While all modules and skins are virtually 100% source code compatible (with a few strategic #if MVC6), the framework code (mostly the Core package) was not so lucky. Still, it's the same code base and we plan on supporting both ASP.NET 4 and ASP.NET Core for a while, with the same exact feature set.

This is a list of the main incompatibilities we encountered upgrading YetaWF to run on ASP.NET Core. Some of these items took a lot of time to address, others were minor annoyances and then there are all the small changes we didn't list. Overall the conversion to ASP.NET Core took about two months, which was aggravated by Visual Studio's move from .csproj to .xproj back to .csproj.

MVC Changes

The loss of System.Web.Mvc.WebViewPage and System.Web.Mvc.Controller without equivalent functionality (the new classes lack some of the basic features) along with this defect (https://github.com/aspnet/Mvc/issues/5397) caused the most issues during upgrading, probably totaling 50% of the time spent.

System.Web.Mvc.Controller

If you derived your own classes from System.Web.Mvc.Controller to use as base class for your controllers, you know the pain. There are so many changes... Good luck.

System.Web.Mvc.WebViewPage

If you derived your own classes from System.Web.Mvc.WebViewPage to use as base class for your pages, you know the pain. There are so many changes... Good luck.

Action

No more System.Web.Mvc.Html.ChildActionExtensions??? This was used to render modules within a page. And it's gone.

ViewComponents should solve the problem? Well not for Ajax requests, so, no. There was a partial solution here which inspired our own YetaWF.Core.Controllers.Shared.HtmlHelperActionExtensions Action() implementation.

ActionResult

Any class derived from ActionResult has to change its ExecuteResult method as the parameter has changed to use the new ActionContext, instead of ControllerContext.

public override void ExecuteResult(ActionContext context)

JsonResult

Expects an object in its constructor instead of using the Data property, which no longer exists.

Areas

The method used to register Areas has changed with MapAreaRoute. Decorating all controllers (classes or actions) with the AreaAttribute is not necessary with YetaWF as areas are determined based on package implementing a controller.

MvcHtmlString

This has been removed. It's unclear why we ever used this class as it adds little functionality. It has been eliminated in favor of HtmlString.

Validation Attributes, IClientValidatable

Pretty much any custom validation attributes have to be changed if they provide client side validation. IClientValidatable has been replaced by IClientModelValidator and requires implementation of the AddValidation() method.

AdditionalMetadata Attribute

Gone. And nothing to replace it. WHY? Here is how you can implement your own.

Model Validation

There has been a subtle change in model validation which causes complex types to be validated even if their value is null or they don't have a Setter. MVC5 did not validate such properties.
This requires extensive testing to hit all controllers with valid and invalid data. Fortunately, YetaWF already had a (custom) ReadOnlyAttribute, which we could extend by adding the IPropertyValidationFilter interface. That is another reason we need to use ASP.NET Core 1.2 2.0 (Edited - 4/28/2017) which adds IPropertyValidationFilter support (see https://github.com/aspnet/Mvc/pull/5676/commits).

Error Handling

Error handling in controllers and pages has changed and must be resolved with middleware.

Web.config - Application Settings

All application specific settings are now located in an application.json configuration file. This can be retrieved using IConfigurationRoot. There is no support to write the configuration file, which means you have to read/write the configuration file anyway if you need to make updates from your application. And unlike MVC5, your site will not automatically restart when making changes to the file.

TagBuilder

What a mess... See comments here.

HtmlHelper

It's now called IHtmlHelper...

<input id=..>

Input tags receive gratuitous ids... See comments here.

ASP.NET Core Changes

Interestingly enough, even though some of these could have had a significant impact, most of the code was already abstract enough to simply use a dual path, resulting in minimal changes.

HttpCookie

No more HttpCookie. Use Response.Cookies.Append instead.

Query String, Forms

Dealing with query string, forms, RouteCollectionValues, anonymous objects has been abstracted into the QueryHelper class as all these collections are incompatible now.

HttpPostedFileBase

File uploads use the HttpPostedFileBase. It has been replaced by IFormFile which is used almost identically.

HttpContext.Current.Cache

Replaced by IMemoryCache.

HttpSessionState

Now based on ISession.

Http Handlers

These must be converted to middleware. This is actually quite straightforward. Read Microsoft's documentation about this.

Miscellaneous

Because of the switch to Bower, scripts and css files for referenced packages are no longer in the site's /Scripts and /Content folders. They are now located in the /lib folder.

No Comments

Be the first to add a comment!

Add New Comment

Complete this simple form to add a comment to this blog entry.