索引:html
目錄索引redis
Controller methods and views數據庫
控制器方法與視圖瀏覽器
2017-3-7 9 分鐘閱讀時長 做者 安全
By Rick Anderson服務器
We have a good start to the movie app, but the presentation is not ideal.mvc
咱們在movie 應用上已經有了一個好的開始,可是表現層不是很理想。app
We don't want to see the time (12:00:00 AM in the image below) and ReleaseDateshould be two words.asp.net
咱們不想看到下圖中顯示的(12:00:00 AM)而且 ReleaseDate 字段應該顯示爲兩個單詞。async
Open the Models/Movie.cs file and add the highlighted lines shown below:
打開 Models/Movie.cs 文件而且添加下面高亮行的代碼:
1 using System; 2 3 using System.Collections.Generic; 4 5 using System.Linq; 6 7 using System.Threading.Tasks; 8 9 10 11 namespace MvcMovie.Models 12 13 { 14 15 public class Movie 16 17 { 18 19 public int ID { get; set; } 20 21 public string Title { get; set; } 22 23 24 25 [Display(Name = "Release Date")] 26 27 [DataType(DataType.Date)] 28 29 public DateTime ReleaseDate { get; set; } 30 31 public string Genre { get; set; } 32 33 public decimal Price { get; set; } 34 35 } 36 37 }
Right click on a red squiggly line > Quick Actions and Refactorings.
在紅波浪線上右擊,選擇 Quick Actions and Refactorings.
Tap using System.ComponentModel.DataAnnotations;
點擊 using System.ComponentModel.DataAnnotations
Visual studio adds using System.ComponentModel.DataAnnotations;.
VS將自動添加 using System.ComponentModel.DataAnnotations 。
Let's remove the using statements that are not needed.
讓移除不須要的 using 語句 。
They show up by default in a light grey font. Right click anywhere in the Movie.cs file > Remove and Sort Usings.
他們默認以灰色字體顯示。右擊 Movie.cs 文件的任何地方,選擇 Remove and Sort Usings 。
The updated code:
更新後的代碼以下:
1 using System; 2 3 using System.ComponentModel.DataAnnotations; 4 5 6 7 namespace MvcMovie.Models 8 9 { 10 11 public class Movie 12 13 { 14 15 public int ID { get; set; } 16 17 public string Title { get; set; } 18 19 20 21 [Display(Name = "Release Date")] 22 23 [DataType(DataType.Date)] 24 25 public DateTime ReleaseDate { get; set; } 26 27 public string Genre { get; set; } 28 29 public decimal Price { get; set; } 30 31 } 32 33 }
We'll cover DataAnnotations in the next tutorial.
咱們將在接下來的教程中講解數據註解特性。
The Display attribute specifies what to display for the name of a field (in this case "Release Date" instead of "ReleaseDate").
Display 特性特別的指定了該字段在界面顯示時所要顯示的名字(用 Release Date 代替了 ReleaseDate)。
The DataType attribute specifies the type of the data (Date), so the time information stored in the field is not displayed.
DataType 特性特別指定了數據的顯示類型(日期),所以字段裏面存儲的時間信息就再也不顯示了。
Browse to the Movies controller and hold the mouse pointer over an Edit link to see the target URL.
導航到 Movies 地址,在頁面上將鼠標放到 Edit 連接上,並查看目標URL.
The Edit, Details, and Delete links are generated by the MVC Core Anchor Tag Helper in the Views/Movies/Index.cshtml file.
在Views/Movies/Index.cshtml 文件中的 Edit, Details和 Delete 連接由mvc連接幫助類自動生成的。
1 <a asp-action="Edit" asp-route-id="@item.ID">Edit</a> | 2 3 <a asp-action="Details" asp-route-id="@item.ID">Details</a> | 4 5 <a asp-action="Delete" asp-route-id="@item.ID">Delete</a> 6 7 </td> 8 9 </tr>
Tag Helpers enable server-side code to participate in creating and rendering HTML elements in Razor files.
Tag Helpers 是在服務端參與產生與渲染HTML的。
In the code above,
在上面的代碼中,
the AnchorTagHelperdynamically generates the HTML href attribute value from the controller action method and route id.
AnchorTagHelper 動態的生成了html中的href 特徵屬性的值 (控制器方法與方法的id參數)。
You use View Source from your favorite browser or use the developer tools to examine the generated markup.
你可使用瀏覽器的 View Source 或開發工具查看 自動生成的 html 標記。
A portion of the generated HTML is shown below:
部分html以下所示:
1 <td> 2 3 <a href = "/Movies/Edit/4" > Edit </ a > | 4 5 < a href="/Movies/Details/4">Details</a> | 6 7 <a href = "/Movies/Delete/4" > Delete </ a > 8 9 </ td >
Recall the format for routing set in the Startup.cs file:
回想 Startup.cs 文件中的路由設置,以下:
1 app.UseMvc(routes => 2 3 { 4 5 routes.MapRoute( 6 7 name: "default", 8 9 template: "{controller=Home}/{action=Index}/{id?}"); 10 11 });
ASP.NET Core translates http://localhost:1234/Movies/Edit/4 into a request to the Edit action method of the Movies controller with the parameter Id of 4. (Controller methods are also known as action methods.)
Asp.net core 翻譯 http://localhost:1234/Movies/Edit/4 地址爲對 Movies 控制器中方法Edit 的請求,而且參數爲4.
Tag Helpers are one of the most popular new features in ASP.NET Core.
Tag Helpers 是asp.net core 中最受歡迎的特色之一。
See Additional resources for more information.
查看 Additional resources 瞭解更多信息。
Open the Movies controller and examine the two Edit action methods.
打開 Movies 控制器,查看兩個 Edit 方法的代碼。
The following code shows the HTTP GET Edit method, which fetches the movie and populates the edit form generated by the Edit.cshtml Razor file.
下面的代碼是 HTTP GET Edit 方法,他讀取了movie數據並填充了由 Edit.cshtml 文件生成的編輯表單。
1 // GET: Movies/Edit/5 2 3 public async Task<IActionResult> Edit(int? id) 4 5 { 6 7 if (id == null) 8 9 { 10 11 return NotFound(); 12 13 } 14 15 16 17 var movie = await _context.Movie.SingleOrDefaultAsync(m => m.ID == id); 18 19 if (movie == null) 20 21 { 22 23 return NotFound(); 24 25 } 26 27 return View(movie); 28 29 }
The following code shows the HTTP POST Edit method, which processes the posted movie values:
下面的代碼展現了 HTTP POST Edit 方法,他處理了post請求過來的movie數據:
1 // POST: Movies/Edit/5 2 3 // To protect from overposting attacks, please enable the specific properties you want to bind to, for 4 5 // more details see http://go.microsoft.com/fwlink/?LinkId=317598. 6 7 [HttpPost] 8 9 [ValidateAntiForgeryToken] 10 11 public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie) 12 13 { 14 15 if (id != movie.ID) 16 17 { 18 19 return NotFound(); 20 21 } 22 23 24 25 if (ModelState.IsValid) 26 27 { 28 29 try 30 31 { 32 33 _context.Update(movie); 34 35 await _context.SaveChangesAsync(); 36 37 } 38 39 catch (DbUpdateConcurrencyException) 40 41 { 42 43 if (!MovieExists(movie.ID)) 44 45 { 46 47 return NotFound(); 48 49 } 50 51 else 52 53 { 54 55 throw; 56 57 } 58 59 } 60 61 return RedirectToAction("Index"); 62 63 } 64 65 return View(movie); 66 67 }
The [Bind] attribute is one way to protect against over-posting.
[Bind] 特性標記是一種post攻擊防禦方式。
You should only include properties in the [Bind] attribute that you want to change.
你應當只作 [Bind] 特徵類中包含的字段的變動。
See Protect your controller from over-posting for more information.
查看 Protect your controller from over-posting 以得到更多信息。
ViewModels provide an alternative approach to prevent over-posting.
ViewModels 提供一種預防 over-posting 攻擊的方式。
Notice the second Edit action method is preceded by the [HttpPost] attribute.
注意第二個 Edit 方法被 [HttpPost] 特徵類修飾。
1 // POST: Movies/Edit/5 2 3 // To protect from overposting attacks, please enable the specific properties you want to bind to, for 4 5 // more details see http://go.microsoft.com/fwlink/?LinkId=317598. 6 7 [HttpPost] 8 9 [ValidateAntiForgeryToken] 10 11 public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie) 12 13 { 14 15 if (id != movie.ID) 16 17 { 18 19 return NotFound(); 20 21 } 22 23 24 25 if (ModelState.IsValid) 26 27 { 28 29 try 30 31 { 32 33 _context.Update(movie); 34 35 await _context.SaveChangesAsync(); 36 37 } 38 39 catch (DbUpdateConcurrencyException) 40 41 { 42 43 if (!MovieExists(movie.ID)) 44 45 { 46 47 return NotFound(); 48 49 } 50 51 else 52 53 { 54 55 throw; 56 57 } 58 59 } 60 61 return RedirectToAction("Index"); 62 63 } 64 65 return View(movie); 66 67 }
The HttpPost attribute specifies that this Edit method can be invoked only for POST requests.
HttpPost 標記特別指定了 Edit 方法只能被 POST 請求調用。
You could apply the [HttpGet] attribute to the first edit method, but that's not necessary because [HttpGet] is the default.
你能夠在第一個 edit 方法上使用 [HttpGet] 特徵類,單他不是必須的,由於方法默認是 [HttpGet] 請求的。
The ValidateAntiForgeryToken attribute is used to prevent forgery of a requestand is paired up with an anti-forgery token generated in the edit view file (Views/Movies/Edit.cshtml).
ValidateAntiForgeryToken 標記類使用了預防僞造請求,並與 edit 視圖生成的反僞造令牌是配對的。
The edit view file generates the anti-forgery token with the Form Tag Helper.
edit 視圖生成的anti-forgery 令牌是經過 Form Tag Helper 生成的。
1 <form asp-action="Edit">
The Form Tag Helper generates a hidden anti-forgery token that must match the [ValidateAntiForgeryToken] generated anti-forgery token in the Edit method of the Movies controller.
Form Tag Helper 生成了一個隱藏域的令牌字段,而且他是匹配Movies控制器中Edit 方法上的[ValidateAntiForgeryToken] 標記生成的令牌的。
For more information, see Anti-Request Forgery.
查看 Anti-Request Forgery ,以得到更多信息。
The HttpGet Edit method takes the movie ID parameter, looks up the movie using the Entity Framework SingleOrDefaultAsync method, and returns the selected movie to the Edit view.
HttpGet Edit 方法獲取 ID 參數,查看 EF 的 SingleOrDefaultAsync 方法,它會查找並將movie數據返回給 Edit 視圖。
If a movie cannot be found, NotFound (HTTP 404) is returned.
若是movie數據沒有找到,將返回 NotFound 。
1 // GET: Movies/Edit/5 2 3 public async Task<IActionResult> Edit(int? id) 4 5 { 6 7 if (id == null) 8 9 { 10 11 return NotFound(); 12 13 } 14 15 16 17 var movie = await _context.Movie.SingleOrDefaultAsync(m => m.ID == id); 18 19 if (movie == null) 20 21 { 22 23 return NotFound(); 24 25 } 26 27 return View(movie); 28 29 }
When the scaffolding system created the Edit view, it examined the Movie class and created code to render <label> and <input> elements for each property of the class.
當MVC基架系統建立了 Edit 視圖,它會自動檢查 Movie 類的每一個屬性,並未每一個屬性建立HTML元素。
The following example shows the Edit view that was generated by the Visual Studio scaffolding system:
下面的例子展現了VS基架系統自動生成的 Edit 視圖:
1 @model MvcMovie.Models.Movie 2 3 4 5 @{ 6 7 ViewData["Title"] = "Edit"; 8 9 } 10 11 12 13 <h2>Edit</h2> 14 15 16 17 <form asp-action="Edit"> 18 19 <div class="form-horizontal"> 20 21 <h4>Movie</h4> 22 23 <hr /> 24 25 <div asp-validation-summary="ModelOnly" class="text-danger"></div> 26 27 <input type="hidden" asp-for="ID" /> 28 29 <div class="form-group"> 30 31 <label asp-for="Title" class="col-md-2 control-label"></label> 32 33 <div class="col-md-10"> 34 35 <input asp-for="Title" class="form-control" /> 36 37 <span asp-validation-for="Title" class="text-danger"></span> 38 39 </div> 40 41 </div> 42 43 <div class="form-group"> 44 45 <label asp-for="ReleaseDate" class="col-md-2 control-label"></label> 46 47 <div class="col-md-10"> 48 49 <input asp-for="ReleaseDate" class="form-control" /> 50 51 <span asp-validation-for="ReleaseDate" class="text-danger"></span> 52 53 </div> 54 55 </div> 56 57 <div class="form-group"> 58 59 <label asp-for="Genre" class="col-md-2 control-label"></label> 60 61 <div class="col-md-10"> 62 63 <input asp-for="Genre" class="form-control" /> 64 65 <span asp-validation-for="Genre" class="text-danger"></span> 66 67 </div> 68 69 </div> 70 71 <div class="form-group"> 72 73 <label asp-for="Price" class="col-md-2 control-label"></label> 74 75 <div class="col-md-10"> 76 77 <input asp-for="Price" class="form-control" /> 78 79 <span asp-validation-for="Price" class="text-danger"></span> 80 81 </div> 82 83 </div> 84 85 <div class="form-group"> 86 87 <div class="col-md-offset-2 col-md-10"> 88 89 <input type="submit" value="Save" class="btn btn-default" /> 90 91 </div> 92 93 </div> 94 95 </div> 96 97 </form> 98 99 100 101 <div> 102 103 <a asp-action="Index">Back to List</a> 104 105 </div> 106 107 108 109 @section Scripts { 110 111 @{await Html.RenderPartialAsync("_ValidationScriptsPartial");} 112 113 }
Notice how the view template has a @model MvcMovie.Models.Movie statement at the top of the file.
注意視圖文件在頂部爲何會有 @model MvcMovie.Models.Movie 這樣一句話。
@model MvcMovie.Models.Movie specifies that the view expects the model for the view template to be of type Movie.
@model 特別指定了視圖所指望的模型類型是 Movie 類型。
The scaffolded code uses several Tag Helper methods to streamline the HTML markup.
基架代碼使用服務端標記幫助方法來精簡HTML標籤寫法。
The - Label Tag Helper displays the name of the field ("Title", "ReleaseDate", "Genre", or "Price").
Label Tag Helper 顯示字段名稱的名字。
The Input Tag Helper renders an HTML <input> element.
Input Tag Helper 渲染HTML <input> 元素。
The Validation Tag Helper displays any validation messages associated with that property.
Validation Tag Helper 顯示全部的關聯在屬性上的驗證信息。
Run the application and navigate to the /Movies URL. Click an Edit link.
運行程序並導航至 /Movies ,點擊 Edit 連接。
In the browser, view the source for the page. The generated HTML for the <form>element is shown below.
在瀏覽器中,查看頁面源碼。自動生成的 <form> 元素以下所示:
1 <form action="/Movies/Edit/7" method="post"> 2 3 <div class="form-horizontal"> 4 5 <h4>Movie</h4> 6 7 <hr /> 8 9 <div class="text-danger" /> 10 11 <input type="hidden" data-val="true" data-val-required="The ID field is required." id="ID" name="ID" value="7" /> 12 13 <div class="form-group"> 14 15 <label class="control-label col-md-2" for="Genre" /> 16 17 <div class="col-md-10"> 18 19 <input class="form-control" type="text" id="Genre" name="Genre" value="Western" /> 20 21 <span class="text-danger field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span> 22 23 </div> 24 25 </div> 26 27 <div class="form-group"> 28 29 <label class="control-label col-md-2" for="Price" /> 30 31 <div class="col-md-10"> 32 33 <input class="form-control" type="text" data-val="true" data-val-number="The field Price must be a number." data-val-required="The Price field is required." id="Price" name="Price" value="3.99" /> 34 35 <span class="text-danger field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span> 36 37 </div> 38 39 </div> 40 41 <!-- Markup removed for brevity --> 42 43 <div class="form-group"> 44 45 <div class="col-md-offset-2 col-md-10"> 46 47 <input type="submit" value="Save" class="btn btn-default" /> 48 49 </div> 50 51 </div> 52 53 </div> 54 55 <input name="__RequestVerificationToken" type="hidden" value="CfDJ8Inyxgp63fRFqUePGvuI5jGZsloJu1L7X9le1gy7NCIlSduCRx9jDQClrV9pOTTmqUyXnJBXhmrjcUVDJyDUMm7-MF_9rK8aAZdRdlOri7FmKVkRe_2v5LIHGKFcTjPrWPYnc9AdSbomkiOSaTEg7RU" /> 56 57 </form>
The <input> elements are in an HTML <form> element whose action attribute is set to post to the /Movies/Edit/id URL.
<input> 元素在HTML <form> 內的form的 action 屬性被賦值爲 /Movies/Edit/id 的地址。
The form data will be posted to the server when the Save button is clicked.
當 Save 被點擊後,表單中的數據將被髮送至服務器。
The last line before the closing </form>element shows the hidden XSRF token generated by the Form Tag Helper.
在 </form> 元素上的最後一行是 由 Form Tag Helper 自動生成的 XSRF 令牌。
Processing the POST Request
處理 POST 請求
The following listing shows the [HttpPost] version of the Edit action method.
下面的 Edit 方法展現瞭如何被 [HttpPost] 特徵類修飾。
1 // POST: Movies/Edit/5 2 3 // To protect from overposting attacks, please enable the specific properties you want to bind to, for 4 5 // more details see http://go.microsoft.com/fwlink/?LinkId=317598. 6 7 [HttpPost] 8 9 [ValidateAntiForgeryToken] 10 11 public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] Movie movie) 12 13 { 14 15 if (id != movie.ID) 16 17 { 18 19 return NotFound(); 20 21 } 22 23 24 25 if (ModelState.IsValid) 26 27 { 28 29 try 30 31 { 32 33 _context.Update(movie); 34 35 await _context.SaveChangesAsync(); 36 37 } 38 39 catch (DbUpdateConcurrencyException) 40 41 { 42 43 if (!MovieExists(movie.ID)) 44 45 { 46 47 return NotFound(); 48 49 } 50 51 else 52 53 { 54 55 throw; 56 57 } 58 59 } 60 61 return RedirectToAction("Index"); 62 63 } 64 65 return View(movie); 66 67 }
The [ValidateAntiForgeryToken] attribute validates the hidden XSRF token generated by the anti-forgery token generator in the Form Tag Helper
[ValidateAntiForgeryToken] 特徵類將會驗證 由 Form Tag Helper 生成的隱藏域中的 XSRF 令牌,
The model binding system takes the posted form values and creates a Movieobject that's passed as the movie parameter.
模型綁定系統將會讀取post傳遞過來的表單數據並建立 Movie 對象並傳遞給 movie 參數。
The ModelState.IsValid method verifies that the data submitted in the form can be used to modify (edit or update) a Movie object.
ModelState.IsValid 這個方法將會驗證提交的數據是否可被用於 Movie 對象的增刪改。
If the data is valid it's saved.
若是數據有效,數據將會被保存。
The updated (edited) movie data is saved to the database by calling the SaveChangesAsync method of database context.
被更新的數據將會調用 SaveChangesAsync 方法保存到數據庫中。
After saving the data, the code redirects the user to the Index action method of the MoviesController class, which displays the movie collection, including the changes just made.
在保存數據後,代碼會重定向到 Movies 控制器的 Index方法,它將會顯示 movie 列表,其中包括剛作過變動的 movie 數據。
Before the form is posted to the server, client side validation checks any validation rules on the fields.
在表單被提交到服務器前,客戶端將會檢查在字段上的全部驗證規則。
If there are any validation errors, an error message is displayed and the form is not posted.
若是有任何驗證錯誤,錯誤信息就會顯示出來,而且表單就不會被提交。
If JavaScript is disabled, you won't have client side validation but the server will detect the posted values that are not valid, and the form values will be redisplayed with error messages.
若是JS被禁用,你不會有客戶端的驗證信息,可是服務端將會繼續驗證字段值是否有效,而且表單將會顯示出錯誤信息。
Later in the tutorial we examine Model Validation in more detail.
在接下來的教程中咱們將會學習到模型驗證的更多細節信息。
The Validation Tag Helper in the Views/Movies/Edit.cshtml view template takes care of displaying appropriate error messages.
在 Views/Movies/Edit.cshtml 視圖模板中 Validation Tag Helper 將會顯示出適當的錯誤信息。
All the HttpGet methods in the movie controller follow a similar pattern.
在movie控制器中的全部 HttpGet 方法都遵循類似的模式。
They get a movie object (or list of objects, in the case of Index), and pass the object (model) to the view.
他們讀取一個movie對象,並將這個對象傳遞給視圖。
The Create method passes an empty movie object to the Create view.
Create 方法傳遞一個空的movie對象到 Create 視圖。
All the methods that create, edit, delete, or otherwise modify data do so in the [HttpPost] overload of the method.
全部的 create, edit, delete 或其它修改數據的方法都是這樣作的,包括 [HttpPost] 修飾的方法。
Modifying data in an HTTP GETmethod is a security risk.
在 HTTP GET 方法中修改數據是一個安全上的冒險。
Modifying data in an HTTP GET method also violates HTTP best practices and the architectural REST pattern, which specifies that GET requests should not change the state of your application.
用 HTTP GET 方法修改數據違反了HTTP最佳實踐和rest風格結構,它們特別指出了 GET 請求不能夠改變應用數據狀態。
In other words, performing a GET operation should be a safe operation that has no side effects and doesn't modify your persisted data.
換句話說,執行一個 GET 操做,應該是一個沒有任何反作用而且不會修改任何持久化數據的安全操做動做。
Additional resources
額外資源
蒙
2017-08-16 18:26 週三