NET Framework项目移植到NET Core上遇到的一系列坑(2)
目录
- 获取请求的参数
- 获取完整的请求路径
- 获取域名
- 编码
- 文件上传的保存方法
- 获取物理路径
- 返回json属性大小写问题
- webconfig的配置移植到appsettings.json
- 设置区域块mvc的路由器和访问区域块的视图
- netcore访问静态资源文件
- mvc调用子页视图
- 过滤器
- 使用session和解决sessionid一直变化的问题
- md5加密
- path.combine()
- 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 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