七天学会ASP.NET MVC ——线程问题异常处理自定义URL
Posted LisenYang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了七天学会ASP.NET MVC ——线程问题异常处理自定义URL相关的知识,希望对你有一定的参考价值。
本节又带了一些常用的,却很难理解的问题,本节从文件上传功能的实现引出了线程使用,介绍了线程饥饿的解决方法,异常处理方法,了解RouteTable自定义路径 。
系列文章
七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC
七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递
七天学会ASP.NET MVC (三)——ASP.Net MVC 数据处理
七天学会ASP.NET MVC (五)——Layout页面使用和用户角色管理
七天学会ASP.NET MVC (六)——线程问题、异常处理、自定义URL
目录
实验27——添加批量上传选项
关于实验27
实验27存在的问题
解决方法
实验28——解决线程饥饿问题
实验29——异常处理—显示自定义错误页面
关于实验29
理解实验29中的限制
实验30—异常处理—日志异常
关于实验30
理解RouteTable
理解Asp.net MVC 请求周期
实验31—实现用户友好URLs
关于实验31
总结
实验27——添加批量上传选项
在实验27中,我们将提供一个选项,供用户选择上传Employee记录文件(CSV格式)。
我们会学习以下知识:
1. 如何使用文件上传控件
2. 异步控制器
1. 创建 FileUploadViewModel
在ViewModels文件夹下新建类“FileUploadViewModel”,如下:
1: public class FileUploadViewModel: BaseViewModel
2:
3: public HttpPostedFileBase fileUpload get; set ;
4:
HttpPostedFileBase 将通过客户端提供上传文件的访问入口。
2. 创建 BulkUploadController 和Index action 方法
新建 controller“BulkUploadController”,并实现Index Action 方法,如下:
1: public class BulkUploadController : Controller
2:
3: [HeaderFooterFilter]
4: [AdminFilter]
5: public ActionResult Index()
6:
7: return View(new FileUploadViewModel());
8:
9:
Index方法与 HeaderFooterFilter 和 AdminFilter属性绑定。HeaderFooterFilter会确保页眉和页脚数据能够正确传递到ViewModel中,AdminFilter限制非管理员用户的访问。
3.创建上传View
创建以上Action方法的View。View名称应为 index.cshtml,且存放在“~/Views/BulkUpload”文件夹下。
4. 设计上传View
在View中输入以下内容:
1: @using WebApplication1.ViewModels
2: @model FileUploadViewModel
3: @
4: Layout = "~/Views/Shared/MyLayout.cshtml";
5:
6:
7: @section TitleSection
8: Bulk Upload
9:
10: @section ContentBody
11: <div>
12: <a href="/Employee/Index">Back</a>
13: <form action="/BulkUpload/Upload" method="post" enctype="multipart/form-data">
14: Select File : <input type="file" name="fileUpload" value="" />
15: <input type="submit" name="name" value="Upload" />
16: </form>
17: </div>
18:
如上,FileUploadViewModel中属性名称与 input[type="file"]的名称类似,都称为“fileUpload”。我们在Model Binder中已经讲述了名称属性的重要性,注意:在表单标签中,有一个额外的属性是加密的,会在实验结尾处讲解。
5. 创建业务层上传方法
在 EmployeeBusinessLayer中新建方法 UploadEmployees,如下:
1: public void UploadEmployees(List<Employee> employees)
2:
3: SalesERPDAL salesDal = new SalesERPDAL();
4: salesDal.Employees.AddRange(employees);
5: salesDal.SaveChanges();
6: <employee>
7: </employee>
6. 创建Upload Action 方法
创建Action 方法,并命名为 “BulkUploadController”,如下:
1: [AdminFilter]
2: public ActionResult Upload(FileUploadViewModel model)
3:
4: List<Employee> employees = GetEmployees(model);
5: EmployeeBusinessLayer bal = new EmployeeBusinessLayer();
6: bal.UploadEmployees(employees);
7: return RedirectToAction("Index","Employee");
8:
9:
10: private List<Employee> GetEmployees(FileUploadViewModel model)
11:
12: List<Employee> employees = new List<Employee>();
13: StreamReader csvreader = new StreamReader(model.fileUpload.InputStream);
14: csvreader.ReadLine(); // Assuming first line is header
15: while (!csvreader.EndOfStream)
16:
17: var line = csvreader.ReadLine();
18: var values = line.Split(',');//Values are comma separated
19: Employee e = new Employee();
20: e.FirstName = values[0];
21: e.LastName = values[1];
22: e.Salary = int.Parse(values[2]);
23: employees.Add(e);
24:
25: return employees;
26:
AdminFilter会绑定到Upload action方法中,限制非管理员用户的访问。
7. 创建BulkUpload链接
打开 “Views/Employee”文件夹下的 AddNewLink.cshtml 文件,输入BulkUpload链接,如下:
<a href="/Employee/AddNew">Add New</a>
<a href="/BulkUpload/Index">BulkUpload</a>
8.运行
8.1 创建一个样本文件来测试,如图所示
id="iframe_0.34527086733685164" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://www.codeproject.com/KB/aspnet/1002109/1.JPG?_=0.013943667427406936%22%20style=%22border:none;max-width:711px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.34527086733685164',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border-style: none; border-width: initial; width: 254px; height: 120px;">
8.2 运行,点击BulkUpload链接
id="iframe_0.7450610928504269" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://www.codeproject.com/KB/aspnet/1002109/2.JPG?_=0.7736347179864274%22%20style=%22border:none;max-width:711px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.7450610928504269',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border-style: none; border-width: initial; width: 451px; height: 161px;">
选择文件并点击确认
id="iframe_0.47173995661524626" src="data:text/html;charset=utf8,%3Cimg%20id=%22img%22%20src=%22http://www.codeproject.com/KB/aspnet/1002109/3.JPG?_=0.3318779638779388%22%20style=%22border:none;max-width:711px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.47173995661524626',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no" style="margin: 0px; padding: 0px; border-style: none; border-width: initial; width: 424px; height: 180px;">
关于实验 27
为什么在实验27中不需要验证?
在该选项中添加客户端和服务器端验证需要读者自行添加的,以下是添加验证的提示:
- 服务器端验证可使用Data Annotations。
- 客户端验证可利用客户端的数据解释和执行jQuery的验证。必须手动设置自定义数据属性,因为并没有将Htmlhelper 方法设置为文件输入。
- 客户端验证可编写javascript 代码,通过点击按钮来实现。这个方法并不是很难,由于文件输入是由输入控件完成,值可以在JavaScript中获取及验证 。
什么是 HttpPostedFileBase?
HttpPostedFileBase将通过客户端提供文件上传的访问入口,Model Binder 会在Post请求期间更新 FileUploadViewModel类中的所有属性值。我们在FileUploadViewModel内部只有一个属性,Model Binder会通过客户端设置它实现文件上传。
是否会提供多文件的输入控件?
是,有两种方法可以实现:
1. 创建多文件输入控件,每个控件有唯一的名称,FileUploadViewModel类会为每个控件创建 HttpPostedFileBase类型的属性,每个属性名称应该与控件名称匹配。
2. 创建多文件输入控件,每个控件有相同的名称,创建类型的List列表,代替创建多个HttpPostedFileBase类型的属性。
enctype="multipart/form-data" 是用来做什么的?
该属性指定了post 数据的编码类型,默认属性值是”application/x-www-form-urlencoded“
例1—登录窗体会给服务器发送以下Post 请求
1: POST /Authentication/DoLogin HTTP/1.1
2: Host: localhost:8870
3: Connection: keep-alive
4: Content-Length: 44
5: Content-Type: application/x-www-form-urlencoded
6: ...
7: ...
8: UserName=Admin&Passsword=Admin&BtnSubmi=Login
所有输入值会被作为发送的值的一部分,以”key/value“的形式发送。
当 enctype="multipart/form-data" 属性被加入Form标签中,以下post 请求会被发送到服务器。
1: POST /Authentication/DoLogin HTTP/1.1
2: Host: localhost:8870
3: Connection: keep-alive
4: Content-Length: 452
5: Content-Type: multipart/form-data; boundary=----WebKitFormBoundarywHxplIF8cR8KNjeJ
6: ...
7: ...
8: ------WebKitFormBoundary7hciuLuSNglCR8WC
9: Content-Disposition: form-data; name="UserName"
10:
11: Admin
12: ------WebKitFormBoundary7hciuLuSNglCR8WC
13: Content-Disposition: form-data; name="Password"
14:
15: Admin
16: ------WebKitFormBoundary7hciuLuSNglCR8WC
17: Content-Disposition: form-data; name="BtnSubmi"
18:
19: Login
20: ------WebKitFormBoundary7hciuLuSNglCR8WC--
如上所示,Form会在多部分post发送,每部分都是被分界线分割的,每部分包含单值。
如果form标签包含文件输入控件的话,enctype必须被设置为”multipart/form-data“。
为什么有时候需要设置 encType 为 “multipart/form-data”,而有时候不需要设置?
当encType 设置为”multipart/form-data“,将会实现Post数据和上传文件的功能,当然也会增加请求的size 增加,请求size 越大意味着性能越低。因此得出的最佳实践经验需要设置为默认的”application/x-www-form-urlencoded“。
为什么在实验27中创建ViewModel?
在View中已经有一个控件了,我们需要通过直接添加 HttpPostedFileBase类型的参数,并命名为”fileUpload“实现相同的结果,从而替代创建独立的ViewModel。
1: public ActionResult Upload(HttpPostedFileBase fileUpload)
2:
3:
创建 ViewModel是最好的方法,Controller应该以 ViewModel的形式给View发送数据,且数据必须来自Controller。
以上问题的解决方法
是否存在疑虑,当发送请求时,如何获取响应?
七天学会ASP.NET MVC ——深入理解ASP.NET MVC
七天学会ASP.NET MVC ——ASP.NET MVC 数据传递
七天学会ASP.NET MVC ——ASP.Net MVC 数据处理