NET Framework項目移植到NET Core上遇到的一系列坑(2)


目錄

  1. 獲取請求的參數
  2. 獲取完整的請求路徑
  3. 獲取域名
  4. 編碼
  5. 文件上傳的保存方法
  6. 獲取物理路徑
  7. 返回Json屬性大小寫問題
  8. webconfig的配置移植到appsettings.json
  9. 設置區域塊MVC的路由器和訪問區域塊的視圖
  10. NetCore訪問靜態資源文件
  11. MVC調用子頁視圖
  12. 過濾器
  13. 使用session和解決sessionID一直變化的問題
  14. MD5加密
  15. Path.Combine()
  16. DateTime

1.獲取請求的參數

NET Framework版本:

1 Request["xxx"];
2 Request.Files[0];

NET Core版本:

1 Request.Form["xxx"];
2 Request.Form.Files[0];

2.獲取完整的請求路徑

NET Framework版本:

1 Request.RequestUri.ToString(); 

NET Core版本:

1 //先添加引用
2  
3 using Microsoft.AspNetCore.Http.Extensions;
4  
5 //再調用
6 Request.GetDisplayUrl();

 

3.獲取域名

NET Framework版本:

1 HttpContext.Current.Request.Url.Authority

NET Core版本:

1 HttpContext.Request.Host.Value

4.編碼

NET Framework版本:

1 System.Web.HttpContext.Current.Server.UrlEncode("<li class=\"test\"></li>")
2 "%3cli+class%3d%22test%22%3e%3c%2fli%3e"
3 System.Web.HttpContext.Current.Server.UrlDecode("%3cli+class%3d%22test%22%3e%3c%2fli%3e")
4 "<li class=\"test\"></li>"

NET Core版本:

 1 //兩種方法,建議用System.Web.HttpUtility
 2 System.Web.HttpUtility.UrlEncode("<li class=\"test\"></li>");
 3 "%3cli+class%3d%22test%22%3e%3c%2fli%3e"
 4 System.Web.HttpUtility.UrlDecode("%3cli+class%3d%22test%22%3e%3c%2fli%3e");
 5 "<li class=\"test\"></li>"
 6  
 7 System.Net.WebUtility.UrlEncode("<li class=\"test\"></li>")
 8 "%3Cli+class%3D%22test%22%3E%3C%2Fli%3E"
 9 System.Net.WebUtility.UrlDecode("%3Cli+class%3D%22test%22%3E%3C%2Fli%3E")
10 "<li class=\"test\"></li>"
11 System.Net.WebUtility.UrlDecode("%3cli+class%3d%22test%22%3e%3c%2fli%3e")
12 "<li class=\"test\"></li>"

 

 

5.文件上傳的保存方法

NET Framework版本:

1 var file = Request.Files[0];
2  
3 //blockFullPath指保存的物理路徑
4  
5 file.SaveAs(blockFullPath);

NET Core版本:

 1 var file = Request.Form.Files[0];
 2  
 3 //blockFullPath指保存的物理路徑
 4  
 5 using (FileStream fs = new FileStream(blockFullPath, FileMode.CreateNew))
 6  
 7 {
 8  
 9 file.CopyTo(fs);
10  
11 fs.Flush();
12  
13 }

 

 

6.獲取物理路徑

NET Framework版本:

1 //作為一個全局變量獲取物理路徑的方法
2  
3 public string ffmpegPathc = System.Web.Hosting.HostingEnvironment.MapPath("~/Content/ffmpeg/ffmpeg.exe");
4  
5 //獲取在控制器的構造函數里直接調用Server.MapPath
6  
7 ffmpegPathc = Server.MapPath("~/Content/ffmpeg/ffmpeg.exe");

NET Core版本:

 1 //從ASP.NET Core RC2開始,可以通過注入 IHostingEnvironment 服務對象來取得Web根目錄和內容根目錄的物理路徑。代碼如下:
 2 
 3  
 4 [Area("Admin")]
 5  
 6 public class FileUploadController : Controller
 7  
 8 {
 9  
10 private readonly IHostingEnvironment _hostingEnvironment;
11  
12  
13  
14 public string ffmpegPathc = "";//System.Web.Hosting.HostingEnvironment.MapPath("~/Content/ffmpeg/ffmpeg.exe");
15  
16  
17  
18 public FileUploadController(IHostingEnvironment hostingEnvironment)
19  
20 {
21  
22 _hostingEnvironment = hostingEnvironment;
23  
24 ffmpegPathc = _hostingEnvironment.WebRootPath + "/Content/ffmpeg/ffmpeg.exe";
25  
26 }
27  
28 }

 

這樣寫每個控制器就都要寫一個構造函數,很麻煩,所以可以把它抽離出來,寫個公共類去調用。代碼如下:

先自定義一個靜態類:

 1 using Microsoft.AspNetCore.Hosting;
 2  
 3 using Microsoft.Extensions.DependencyInjection;
 4  
 5 using System;
 6  
 7  
 8  
 9 namespace GDSMPlateForm
10  
11 {
12  
13 public static class HttpHelper
14  
15 {
16  
17 public static IServiceProvider ServiceProvider { get; set; }
18  
19  
20  
21 public static string GetServerPath(string path)
22  
23 {
24  
25 return ServiceProvider.GetRequiredService<IHostingEnvironment>().WebRootPath + path;
26  
27 }
28  
29 }
30  
31 }

然后 在startup類下的Configure 方法下:

1 HttpHelper.ServiceProvider = app.ApplicationServices;

startup下的ConfigureServices放下注冊方法(這一步必不可少,但是這里可以不寫,因為IHostingEnvironment 是微軟默認已經幫你注冊了,如果是自己的服務,那么必須注冊)。

1 services.AddSingleton<IHostingEnvironment, HostingEnvironment>();

最后獲取物理路徑就可以這樣直接調用了:

1 public string ffmpegPathc = HttpHelper.GetServerPath("/Content/ffmpeg/ffmpeg.exe");

 

7.返回Json屬性大小寫問題

NET Core返回Json屬性默認都會自動轉為小寫,但項目之前Json屬性有些是大寫的,所以需要配置成不轉化為小寫的形式。

Startup.cs的ConfigureServices方法下添加一行代碼:

1 //Startup需要添加引用
2  
3 using Newtonsoft.Json.Serialization;
4  
5 //返回Json屬性默認大小寫
6  
7 services.AddMvc().AddJsonOptions(o => { o.SerializerSettings.ContractResolver = new DefaultContractResolver(); });

 

8.webconfig的配置移植到appsettings.json

NET Framework版本:

直接可以讀取webconfig配置文件:

string format = System.Configuration.ConfigurationManager.AppSettings["format"].ToString();

NET Core版本:

NET Core不再支持web.config,取而代之的是appsettings.json,所以需要把一些配置移植過去。

例如web.config下的一些配置

 1 <appSettings>
 2  
 3 <add key="ismdb" value="" />
 4  
 5 <add key="webpath" value="" />
 6  
 7 <add key="format" value="jpg,jpeg,png,gif,bmp,tif,svg/mp3,wav/mp4,avi,mpg,wmv,mkv,rmvb,mov,flv/zip/.ppt,.pptx" />
 8  
 9 <add key="imagesize" value="5242880" />
10  
11 <!--1024 * 1024 * 5 -->
12  
13 <add key="musicsize" value="20971520" />
14  
15 <!--1024 * 1024 * 20 -->
16  
17 <add key="mediasize" value="20971520" />
18  
19 <!--1024 * 1024 * 20 -->
20  
21 <add key="packagesize" value="0" />
22  
23 <add key="pptsize" value="0" />
24  
25 </appSettings>

移植到appsettings.json

 1 {
 2  
 3 "Logging": {
 4  
 5 "IncludeScopes": false,
 6  
 7 "LogLevel": {
 8  
 9 "Default": "Warning"
10  
11 }
12  
13 },
14  
15 "webpath": "",
16  
17 "format": "jpg,jpeg,png,gif,bmp,tif,svg/mp3,wav/mp4,avi,mpg,wmv,mkv,rmvb,mov,flv/zip/.ppt,.pptx",
18  
19 "imagesize": "5242880",
20  
21 "musicsize": "20971520",
22  
23 "mediasize": "20971520",
24  
25 "packagesize": "0",
26  
27 "pptsize": "0"
28  
29 }

然后編寫一個類去調用這個appsettings.json

 1 using Microsoft.Extensions.Configuration;
 2  
 3 using System.IO;
 4  
 5  
 6  
 7 namespace GDSMPlateForm
 8  
 9 {
10  
11 public class RConfigureManage
12  
13 {
14  
15 public static string GetConfigure(string key)
16  
17 {
18  
19  
20  
21 //添加 json 文件路徑
22  
23 var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");
24  
25 //創建配置根對象
26  
27 var configurationRoot = builder.Build();
28  
29  
30  
31 //取配置根下的 name 部分
32  
33 string secvalue = configurationRoot.GetSection(key).Value;
34  
35 return secvalue;
36  
37 }
38  
39 }
40  
41 }

調用的方式:

1 string format = RConfigureManage.GetConfigure("format");

 

9.設置區域塊MVC的路由器和訪問區域塊的視圖

NET Framework版本:

NET Framework新建一個區域會自帶一個類設置路由器的,如圖:

 

 
 1 using System.Web.Mvc;
 2  
 3  
 4  
 5 namespace GDSMPlateForm.Areas.Admin
 6  
 7 {
 8  
 9 public class AdminAreaRegistration : AreaRegistration
10  
11 {
12  
13 public override string AreaName
14  
15 {
16  
17 get
18  
19 {
20  
21 return "Admin";
22  
23 }
24  
25 }
26  
27  
28  
29 public override void RegisterArea(AreaRegistrationContext context)
30  
31 {
32  
33 context.MapRoute(
34  
35 "Admin_default",
36  
37 "Admin/{controller}/{action}/{id}",
38  
39 new { action = "Index", id = UrlParameter.Optional }
40  
41 );
42  
43 }
44  
45 }
46  
47 }

NET Core版本:

NET Core新建一個區域不會自帶一個類用於設置路由器,所以需要在Startup類的Configure方法里多加一條路由器設置

 1 app.UseMvc(routes =>
 2  
 3 {
 4  
 5 routes.MapRoute(
 6  
 7 name: "areas",
 8  
 9 template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
10  
11 );
12  
13 });

 

然后需要在每個控制器下添加一個標簽,指定該控制器屬於哪個區域的,如圖:

不加的話訪問不到區域的視圖,報404錯誤。

 

10.NetCore訪問靜態資源文件

NET Framework版本:

NET Framework可以在webconfig下配置這些靜態資源文件

1 <staticContent>
2  
3 <mimeMap fileExtension="." mimeType="image/svg+xml" />
4  
5 <mimeMap fileExtension=".properties" mimeType="application/octet-stream" />
6  
7 </staticContent>

NET Core版本:

NET Core並沒有webconfig,所以需要在Startup類的Configure方法里自己配置。

NET Core項目默認的資源文件存在wwwroot下,可以通過app.UseStaticFiles方法自己定義資源文件的路徑還有類型。

 1 ar provider = new FileExtensionContentTypeProvider();
 2  
 3 provider.Mappings[".properties"] = "application/octet-stream";
 4  
 5 app.UseStaticFiles(new StaticFileOptions
 6  
 7 {
 8  
 9 FileProvider = new PhysicalFileProvider(
10  
11 Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "Content")),
12  
13 RequestPath = "/Content",
14  
15 ContentTypeProvider = provider
16  
17 });

 

11.MVC調用子頁視圖

NET Framework版本:

1 @Html.Action("UserBackView", "UserManage")

NET Core版本:

NET Core不再支持Html.Action(),不過可以手動自己去實現它。

自定義一個靜態類 HtmlHelperViewExtensions,命名空間設置為  Microsoft.AspNetCore.Mvc.Rendering。網上找的一個類,復制過來就行了,如下:

  1 using Microsoft.AspNetCore.Html;
  2  
  3 using Microsoft.AspNetCore.Http;
  4  
  5 using Microsoft.AspNetCore.Mvc.Infrastructure;
  6  
  7 using Microsoft.AspNetCore.Routing;
  8  
  9 using Microsoft.Extensions.DependencyInjection;
 10  
 11 using System;
 12  
 13 using System.IO;
 14  
 15 using System.Threading.Tasks;
 16  
 17  
 18  
 19 namespace Microsoft.AspNetCore.Mvc.Rendering
 20  
 21 {
 22  
 23 public static class HtmlHelperViewExtensions
 24  
 25 {
 26  
 27 public static IHtmlContent Action(this IHtmlHelper helper, string action, object parameters = null)
 28  
 29 {
 30  
 31 var controller = (string)helper.ViewContext.RouteData.Values["controller"];
 32  
 33  
 34  
 35 return Action(helper, action, controller, parameters);
 36  
 37 }
 38  
 39  
 40  
 41 public static IHtmlContent Action(this IHtmlHelper helper, string action, string controller, object parameters = null)
 42  
 43 {
 44  
 45 var area = (string)helper.ViewContext.RouteData.Values["area"];
 46  
 47  
 48  
 49 return Action(helper, action, controller, area, parameters);
 50  
 51 }
 52  
 53  
 54  
 55 public static IHtmlContent Action(this IHtmlHelper helper, string action, string controller, string area, object parameters = null)
 56  
 57 {
 58  
 59 if (action == null)
 60  
 61 throw new ArgumentNullException("action");
 62  
 63  
 64  
 65 if (controller == null)
 66  
 67 throw new ArgumentNullException("controller");
 68  
 69  
 70  
 71  
 72  
 73 var task = RenderActionAsync(helper, action, controller, area, parameters);
 74  
 75  
 76  
 77 return task.Result;
 78  
 79 }
 80  
 81  
 82  
 83 private static async Task<IHtmlContent> RenderActionAsync(this IHtmlHelper helper, string action, string controller, string area, object parameters = null)
 84  
 85 {
 86  
 87 // fetching required services for invocation
 88  
 89 var serviceProvider = helper.ViewContext.HttpContext.RequestServices;
 90  
 91 var actionContextAccessor = helper.ViewContext.HttpContext.RequestServices.GetRequiredService<IActionContextAccessor>();
 92  
 93 var httpContextAccessor = helper.ViewContext.HttpContext.RequestServices.GetRequiredService<IHttpContextAccessor>();
 94  
 95 var actionSelector = serviceProvider.GetRequiredService<IActionSelector>();
 96  
 97  
 98  
 99 // creating new action invocation context
100  
101 var routeData = new RouteData();
102  
103 foreach (var router in helper.ViewContext.RouteData.Routers)
104  
105 {
106  
107 routeData.PushState(router, null, null);
108  
109 }
110  
111 routeData.PushState(null, new RouteValueDictionary(new { controller = controller, action = action, area = area }), null);
112  
113 routeData.PushState(null, new RouteValueDictionary(parameters ?? new { }), null);
114  
115  
116  
117 //get the actiondescriptor
118  
119 RouteContext routeContext = new RouteContext(helper.ViewContext.HttpContext) { RouteData = routeData };
120  
121 var candidates = actionSelector.SelectCandidates(routeContext);
122  
123 var actionDescriptor = actionSelector.SelectBestCandidate(routeContext, candidates);
124  
125  
126  
127 var originalActionContext = actionContextAccessor.ActionContext;
128  
129 var originalhttpContext = httpContextAccessor.HttpContext;
130  
131 try
132  
133 {
134  
135 var newHttpContext = serviceProvider.GetRequiredService<IHttpContextFactory>().Create(helper.ViewContext.HttpContext.Features);
136  
137 if (newHttpContext.Items.ContainsKey(typeof(IUrlHelper)))
138  
139 {
140  
141 newHttpContext.Items.Remove(typeof(IUrlHelper));
142  
143 }
144  
145 newHttpContext.Response.Body = new MemoryStream();
146  
147 var actionContext = new ActionContext(newHttpContext, routeData, actionDescriptor);
148  
149 actionContextAccessor.ActionContext = actionContext;
150  
151 var invoker = serviceProvider.GetRequiredService<IActionInvokerFactory>().CreateInvoker(actionContext);
152  
153 await invoker.InvokeAsync();
154  
155 newHttpContext.Response.Body.Position = 0;
156  
157 using (var reader = new StreamReader(newHttpContext.Response.Body))
158  
159 {
160  
161 return new HtmlString(reader.ReadToEnd());
162  
163 }
164  
165 }
166  
167 catch (Exception ex)
168  
169 {
170  
171 return new HtmlString(ex.Message);
172  
173 }
174  
175 finally
176  
177 {
178  
179 actionContextAccessor.ActionContext = originalActionContext;
180  
181 httpContextAccessor.HttpContext = originalhttpContext;
182  
183 if (helper.ViewContext.HttpContext.Items.ContainsKey(typeof(IUrlHelper)))
184  
185 {
186  
187 helper.ViewContext.HttpContext.Items.Remove(typeof(IUrlHelper));
188  
189 }
190  
191 }
192  
193 }
194  } }

 

然后在Startup中的 ConfigureServices 方法添加:

1 services.AddSingleton<IHttpContextAccessor, HttpContextAccessor();
2  
3 services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

這樣就可以像NET Framework版本一樣去調用子頁面視圖了:

1 @Html.Action("UserBackView", "UserManage")

 

12.過濾器

NET Framework版本

NET Framework版本上Global.asax中Application_Start方法可以做很多配置,過濾器也是其中一種。

  1.  
     1 protected void Application_Start()
     2  
     3 {
     4  
     5 AreaRegistration.RegisterAllAreas();
     6  
     7 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);//全局過濾器集合
     8  
     9 RouteConfig.RegisterRoutes(RouteTable.Routes);
    10  
    11 BundleConfig.RegisterBundles(BundleTable.Bundles);
    12  
    13 }
    14  
    15  
    16  
    17 public class FilterConfig
    18  
    19 {
    20  
    21 public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    22  
    23 {
    24  
    25 filters.Add(new HandleErrorAttribute());
    26  
    27 filters.Add(new LoginCheckFilterAttribute() { IsCheck = true });//自定義一個過濾器
    28  
    29 }
    30  
    31 }
    32  
    33  
    34  
    35 //繼承過濾器基類並重寫方法
    36  
    37 public class LoginCheckFilterAttribute : ActionFilterAttribute
    38  
    39 {
    40  
    41 //表示是否檢查
    42  
    43 public bool IsCheck { get; set; }
    44  
    45 //Action方法執行之前執行此方法
    46  
    47 public override void OnActionExecuting(ActionExecutingContext filterContext)
    48  
    49 {
    50  
    51 base.OnActionExecuting(filterContext);
    52  
    53 if (IsCheck)
    54  
    55 {
    56  
    57 //添加自己的邏輯
    58  
    59 }
    60  
    61 }
    62  
    63 }

     

NET Core版本:

NET Core不在支持Global.asax,很多配置寫在Startup里。過濾器的添加方法如下:

 
 1 public void ConfigureServices(IServiceCollection services)
 2  
 3 {
 4  
 5 services.AddMvc(options =>
 6  
 7 {
 8  
 9 options.Filters.Add(typeof(AuthorizationFilters));// 自定義一個類AuthorizationFilters,添加身份驗證過濾器
10  
11 });
12  
13 }
14  
15  
16  
17 /// <summary>
18  
19 /// 身份認證類繼承IAuthorizationFilter接口
20  
21 /// </summary>
22  
23 public class AuthorizationFilters :IAuthorizationFilter
24  
25 {
26  
27 /// <summary>
28  
29 /// 請求驗證,當前驗證部分不要拋出異常,ExceptionFilter不會處理
30  
31 /// </summary>
32  
33 /// <param name="context">請求內容信息</param>
34  
35 public void OnAuthorization(AuthorizationFilterContext context)
36  
37 {
38  
39 //寫自己的邏輯
40  
41 }
42  
43 }

 

13.使用session和解決sessionID一直變化的問題

NET Core版本:

在Startup類里添加session配置

 
 1 public void ConfigureServices(IServiceCollection services)
 2  
 3 {
 4  
 5 services.AddDistributedMemoryCache();
 6  
 7 services.AddSession(option =>
 8  
 9 { //設置session過期時間
10  
11 option.IOTimeout = TimeSpan.FromHours(1);
12  
13 option.IdleTimeout = TimeSpan.FromHours(1);
14  
15 });
16  
17 services.AddMvc();
18  
19 }
20  
21  
22  
23 public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider svp)
24  
25 {
26  
27 app.UseSession();//必須在app.UseMvc之前,否則報錯
28  
29 app.UseMvc(routes =>
30  
31 {
32  
33 routes.MapRoute(
34  
35 name: "default",
36  
37 template: "{controller=Home}/{action=Index}/{id?}");
38  
39 });
40  
41 }

 

配置完成后session就可以使用了,不過當Session保存有值,id才不會改變,沒有值每次刷新都會變,可以給在使用session時可以給session隨便賦個值以保證sessionid不會一直變化。

 
1 HttpContext.Session.Set("login", Encoding.UTF8.GetBytes("login"));
2  
3 string sessionid = HttpContext.Session.Id;

14.MD5加密

NET Framework版本:

1  
2 //參數str類型是string
3  
4 System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(str, "MD5");

 

NET Core版本:用以下這個方法替換了

 
 1 /// <summary>
 2  
 3 /// 32位MD5加密
 4  
 5 /// </summary>
 6  
 7 /// <param name="input"></param>
 8  
 9 /// <returns></returns>
10  
11 private static string Md5Hash(string input)
12  
13 {
14  
15 MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
16  
17 byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));
18  
19 StringBuilder sBuilder = new StringBuilder();
20  
21 for (int i = 0; i < data.Length; i++)
22  
23 {
24  
25 sBuilder.Append(data[i].ToString("x2"));
26  
27 }
28  
29 return sBuilder.ToString();
30  
31 }

 

15.Path.Combine()

該方法是路徑拼接,在NET Framework版本和NET Core版本同樣支持,不過用Path.Combine拼接出來的路徑是這樣的:xxxx\\xxxx,用的是“\\”,這種路徑在Window系統上可以正常運行,但是在Linux上是無法定位到准確的路徑的。Linux上的路徑是這樣的:xxxx/xxxx。所以當我們用Path.Combine這個方法時最好再配合一個替換方法:

Path.Combine(path1,path2).Replace("\\","/");

 

16.DateTime

1  // 方法在不同平台返回的時間格式不一樣,即使使用ToString("yyyy/MM/dd")希望轉成'2019/04/18'這種格式,但在Centos7平台下它還是變成了‘2019-04-18’這樣,可以考慮用Replace方法去替換。
2   core 2.1 DateTime.Now.ToString() 

 原文地址:https://www.cnblogs.com/lonelyxmas/p/12001657.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM