ASP.NET Core是微軟新推出的支持跨平臺、高性能、開源的開發框架,它的優點沒必要多說,由於已經說得太多了。固然,如今依然有着數量龐大的系統運行於.NET Framework上,因爲有大量的Break Changes,不少項目項目團隊也不敢貿然升級,其中的考量也不所有是技術緣由,更多的可能仍是業務推動因素。css
小編自年前開始考慮升級一套電商系統,原先是基於.NET Framework 4.5的,打算直接升級到.NET Core 3.1,因爲系統規模比較龐大,因此一旦開工就是一個漫長的工程,個人博客也在很長時間沒有再更新,有點對不起讀者了。html
年前第一次重構時,因爲低估這套系統的複雜性再加上有些冒進,步子邁得有點大,出現了不少問題,不得不從新開始。這一次重構先易後難,步步爲營,難題統一在後面解決,到如今已經完成了所有工程的百分之八十,後面的也沒有太困難了,因此特意抽出時間小結一下。ajax
類庫部分的遷移應該是最簡單的了,我是建立了一個新的類庫,而後把代碼copy過去,不多有地方須要修改,固然了有一些引用的第三方類庫須要特殊對待,如Automapper、Autofac、FluentValidation等,這些也很簡單,看看文檔就行。session
.NET Framework中,會有一些經常使用的封裝庫,如Session、Cookie和HttpRuntime等,這些變化比較大,因此本身在Startup中啓用。mvc
1: app.UseSession(new SessionOptions
2: {
3: Cookie = new CookieBuilder
4: {
5:
6: },
7: IdleTimeout = TimeSpan.FromSeconds(1),
8: IOTimeout = Timeout.InfiniteTimeSpan
9: });
1: services.AddSession();
1: HttpContext.Session.SetString("sessionId", sessionValue);
2: HttpContext.Session.GetString("sessionId");
3: context.Session.Remove("sessionId");
1: Response.Cookies.Append("User", "1", new CookieOptions()
2: {
3: Expires = DateTime.Now.AddMinutes(10)
4: });
5: Response.Cookies.Delete("User");
HttpRuntime的使用,能夠經過IMemoryCache替換,具體的使用方法可參考MSDNapp
順便說一下,靜態資源部分,如JS、CSS、Image、Font這些複製到wwwroot目錄上,另外app.UseStaticFiles();會在模板中出現。框架
一、獲取Controller及Action信息,能夠經過RouteData.Values["controller"].ToString(),RouteData.Values["action"].ToString()函數
二、不少的信息都放到了Request.Header[「」]中,若是以前能夠用過Request直接點出來的,可是如今點不出來了,能夠嘗試使用這種方式,說不許會有意外驚喜。另外有一個相關的常量在這裏出示一下,使用方式即Request.Header[HeaderNames.Authority],固然Request.HttpMethod 改成了 Request.Method。post
1: public static class HeaderNames
2: {
3: public static readonly string Accept;
4: public static readonly string AcceptCharset;
5: public static readonly string AcceptEncoding;
6: public static readonly string AcceptLanguage;
7: public static readonly string AcceptRanges;
8: public static readonly string AccessControlAllowCredentials;
9: public static readonly string AccessControlAllowHeaders;
10: public static readonly string AccessControlAllowMethods;
11: public static readonly string AccessControlAllowOrigin;
12: public static readonly string AccessControlExposeHeaders;
13: public static readonly string AccessControlMaxAge;
14: public static readonly string AccessControlRequestHeaders;
15: public static readonly string AccessControlRequestMethod;
16: public static readonly string Age;
17: public static readonly string Allow;
18: public static readonly string Authority;
19: public static readonly string Authorization;
20: public static readonly string CacheControl;
21: public static readonly string Connection;
22: public static readonly string ContentDisposition;
23: public static readonly string ContentEncoding;
24: public static readonly string ContentLanguage;
25: public static readonly string ContentLength;
26: public static readonly string ContentLocation;
27: public static readonly string ContentMD5;
28: public static readonly string ContentRange;
29: public static readonly string ContentSecurityPolicy;
30: public static readonly string ContentSecurityPolicyReportOnly;
31: public static readonly string ContentType;
32: public static readonly string Cookie;
33: public static readonly string CorrelationContext;
34: public static readonly string Date;
35: public static readonly string DNT;
36: public static readonly string ETag;
37: public static readonly string Expect;
38: public static readonly string Expires;
39: public static readonly string From;
40: public static readonly string Host;
41: public static readonly string IfMatch;
42: public static readonly string IfModifiedSince;
43: public static readonly string IfNoneMatch;
44: public static readonly string IfRange;
45: public static readonly string IfUnmodifiedSince;
46: public static readonly string KeepAlive;
47: public static readonly string LastModified;
48: public static readonly string Location;
49: public static readonly string MaxForwards;
50: public static readonly string Method;
51: public static readonly string Origin;
52: public static readonly string Path;
53: public static readonly string Pragma;
54: public static readonly string ProxyAuthenticate;
55: public static readonly string ProxyAuthorization;
56: public static readonly string Range;
57: public static readonly string Referer;
58: public static readonly string RequestId;
59: public static readonly string RetryAfter;
60: public static readonly string Scheme;
61: public static readonly string SecWebSocketAccept;
62: public static readonly string SecWebSocketKey;
63: public static readonly string SecWebSocketProtocol;
64: public static readonly string SecWebSocketVersion;
65: public static readonly string Server;
66: public static readonly string SetCookie;
67: public static readonly string Status;
68: public static readonly string StrictTransportSecurity;
69: public static readonly string TE;
70: public static readonly string TraceParent;
71: public static readonly string TraceState;
72: public static readonly string Trailer;
73: public static readonly string TransferEncoding;
74: public static readonly string Translate;
75: public static readonly string Upgrade;
76: public static readonly string UpgradeInsecureRequests;
77: public static readonly string UserAgent;
78: public static readonly string Vary;
79: public static readonly string Via;
80: public static readonly string Warning;
81: public static readonly string WebSocketSubProtocols;
82: public static readonly string WWWAuthenticate;
83: public static readonly string XFrameOptions;
84: }
三、Request.IsAjaxRequest性能
這個已經不存在了,能夠自行實現。
1: public static bool IsAjaxRequest(this HttpRequest request)
2: {
3: if (request == null)
4: throw new ArgumentNullException("request");
5:
6: if (request.Headers != null)
7: return request.Headers["X-Requested-With"] == "XMLHttpRequest";
8: return false;
9: }
四、Area註冊
以前的AreaRegistration已經不存在,若是須要設置Area,能夠在每一個Controller上設置[Area(「Admin」)],路由處的註冊能夠考慮以下方式
1: app.UseEndpoints(endpoints =>
2: {
3: endpoints.MapControllerRoute(
4: name: "default",
5: pattern: "{controller=Home}/{action=Index}/{id?}");
6:
7: endpoints.MapControllerRoute(
8: name: "areas",
9: pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
10: );
11: });
五、AbsoluteUri也已經不存在了,可是能夠經過以下方式取代:
1: /// <summary>
2: /// Returns the combined components of the request URL in a fully un-escaped form (except for the QueryString)
3: /// suitable only for display. This format should not be used in HTTP headers or other HTTP operations.
4: /// </summary>
5: /// <param name="request">The request to assemble the uri pieces from.</param>
6: /// <returns>The combined components of the request URL in a fully un-escaped form (except for the QueryString)
7: /// suitable only for display.</returns>
8: public static string GetDisplayUrl(this HttpRequest request);
9:
10: /// <summary>Returns the relative URI.</summary>
11: /// <param name="request">The request to assemble the uri pieces from.</param>
12: /// <returns>The path and query off of <paramref name="request" />.</returns>
13: public static string GetEncodedPathAndQuery(this HttpRequest request);
14:
15: /// <summary>
16: /// Returns the combined components of the request URL in a fully escaped form suitable for use in HTTP headers
17: /// and other HTTP operations.
18: /// </summary>
19: /// <param name="request">The request to assemble the uri pieces from.</param>
20: /// <returns>The encoded string version of the URL from <paramref name="request" />.</returns>
21: public static string GetEncodedUrl(this HttpRequest request);
六、過濾器
以前繼承ActionFilterAttribute,如今實現IActionFilter,註冊方式爲services.AddMvc(o=>o.Filters.Add(new XX())),固然以前的不少過濾器或者Controller基類方法已經不存在了,如Controller OnAuthentication。
IResultFilter中的OnResultExecuting(ResultExecutingContext filterContext)須要經過filterContext.Controller as Controller來獲取默認的Controller。
最後有一個比較重要的類ActionDescriptor,ControllerDescriptor繼承自ActionDescriptor,這裏能夠經過類型轉換獲取相關信息。
以前有不少的FilterAttribute也能夠經過中間件來取代。
七、Action上被去掉的Attribute,如[ValidateInput(false)],[ChildActionOnly]
一、頁面基類型及擴展
以前咱們建立頁面基類型,是經過繼承System.Web.Mvc.WebViewPage<TModel>來實現,如今咱們能夠經過RazorPage<TModel>來取代。
擴展HtmlHelper也換成了IHtmlHelper接口。HtmlString也替換了MvcHtmlString,更上層也以接口方式來取代IHtmlContent。
1: public static IHtmlContent AlignTypeSelect(this IHtmlHelper _html, string xxxxx)
2: {
3: //your code
4: return new HtmlString(html.ToString());
5: }
二、Ajax.BeginForm換成了<form asp-controller="DistributorGrade" asp-action="Save" id="addform" data-ajax="true" data-ajax-method="post" data-ajax-begin="begin" data-ajax-success="success">。當前.NET Core 依然支持Html.BeginForm,不過我建議你們有時間的時候都替換一下,具體請參考下一條。
三、第2條出現的asp-action等是經過Razor Tag Helpers來實現的,不少的自定義須要加入到_ViewImports.cshtml,固然一些引用也能夠統一放到這裏,如@using Microsoft.AspNetCore.Routing,這樣就能夠在當前的Area中做爲全局引用了。
Razor Tag Help是一個十分重要的功能,它使得.NET Core MVC的開發更像是在寫Html語言,更加的清晰,更加具備生產力。
如@Html.TextBoxFor()能夠用經過<input asp-for=」」/>替換,如下圖片摘自MSDN:
Framework MVC的寫法
Core MVC的寫法
一些Tag Help集錦:
四、@Html.Action和@Html.RenderAction能夠經過ViewComponents來取代
1: public class XXXXViewComponent : ViewComponent
2: {
3: public IViewComponentResult Invoke()
4: {
5: return this.View("");
6: }
7: }
調用方式是await Component.InvokeAsync(「XXXXViewComponent「),詳情請點擊連接
五、@MvcHtmlString.Create()可使用new Microsoft.AspNetCore.Html.HtmlString()取代
六、IP地址能夠經過HttpRequest.HttpContext.Connection.RemoteIpAddress獲取
七、以前經過@helper 定義頁面的函數,這個已經被去掉了,如今能夠經過@functions來取代