HTTP服務與Action方法中PUT請求時碰到response.EnsureSuccessStatusCode()的錯誤
這邊主要是參考自ASP.NET MVC 4網站開發美學的第7章:Web API-HTTP服務提供者
其中7.6.4的HTTP服務與Action方法有部份程式碼有錯,所以我就改寫一下,作為日後複習的筆記。
首先要有Northwind的範例資料庫,並放在Models資料夾下,另外在Controller資料夾建立HomeController.cs,以及各cshtml是透過建立強型別檢視並以Scaffold樣板建在Views\Home資料夾下。
完整程式碼如下:
HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
//自訂宣告
using System.Net.Http;
using System.Net.Http.Headers;
using Web_API.Models;
using System.Threading.Tasks;
namespace Web_API.Controllers
{
public class HomeController : Controller
{
//----------------------------------------
//TODO:HTTP服務與Action方法
//----------------------------------------
//副程式
private HttpClient GetClient()
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:12560/");
return client;
}
//GET請求
public ActionResult GetProducts()
{
HttpClient client = GetClient();
var response = client.GetAsync("api/Product").Result;
var products = response.Content.ReadAsAsync>().Result;
return View(products);
}
//Details
public ActionResult GetProductById(string id)
{
HttpClient client = GetClient();
var response = client.GetAsync("api/Product/" + id).Result;
var product = response.Content.ReadAsAsync().Result;
return View(product);
}
//POST請求
public ActionResult PostProduct()
{
return View();
}
[HttpPost]
public ActionResult PostProduct(Products product)
{
HttpClient client = GetClient();
var response = client.PostAsJsonAsync("api/Product", product).Result;
response.EnsureSuccessStatusCode();
return RedirectToAction("GetProducts");
}
//PUT請求
public ActionResult PutProduct(string id)
{
HttpClient client = GetClient();
var response = client.GetAsync("api/Product/" + id).Result;
var product = response.Content.ReadAsAsync().Result;
return View(product);
}
[HttpPost()]
public ActionResult PutProduct(string id, Products product)
{
HttpClient client = GetClient();
var response = client.PutAsJsonAsync("api/Product/" + id, product).Result;
response.EnsureSuccessStatusCode();
return RedirectToAction("GetProducts");
}
//Delete請求
public ActionResult DeleteProduct()
{
return View();
}
[HttpPost()]
public ActionResult DeleteProduct(string id)
{
HttpClient client = GetClient();
var response = client.DeleteAsync("api/Product/"+id).Result;
response.EnsureSuccessStatusCode();
return RedirectToAction("GetProducts");
}
}
}
GetProducts.cshtml
@model IEnumerable<Web_API.Models.Products>
@{
ViewBag.Title = "GetProducts";
}
<h2>GetProducts</h2>
<p>
@Html.ActionLink("Create New", "PostProduct")
</p>
<table>
<tr>
<th>
@Html.DisplayNameFor(model => model.ProductID)
</th>
<th>
@Html.DisplayNameFor(model => model.ProductName)
</th>
<th>
@Html.DisplayNameFor(model => model.SupplierID)
</th>
<th>
@Html.DisplayNameFor(model => model.CategoryID)
</th>
<th>
@Html.DisplayNameFor(model => model.QuantityPerUnit)
</th>
<th>
@Html.DisplayNameFor(model => model.UnitPrice)
</th>
<th>
@Html.DisplayNameFor(model => model.UnitsInStock)
</th>
<th>
@Html.DisplayNameFor(model => model.UnitsOnOrder)
</th>
<th>
@Html.DisplayNameFor(model => model.ReorderLevel)
</th>
<th>
@Html.DisplayNameFor(model => model.Discontinued)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.ProductID)
</td>
<td>
@Html.DisplayFor(modelItem => item.ProductName)
</td>
<td>
@Html.DisplayFor(modelItem => item.SupplierID)
</td>
<td>
@Html.DisplayFor(modelItem => item.CategoryID)
</td>
<td>
@Html.DisplayFor(modelItem => item.QuantityPerUnit)
</td>
<td>
@Html.DisplayFor(modelItem => item.UnitPrice)
</td>
<td>
@Html.DisplayFor(modelItem => item.UnitsInStock)
</td>
<td>
@Html.DisplayFor(modelItem => item.UnitsOnOrder)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReorderLevel)
</td>
<td>
@Html.DisplayFor(modelItem => item.Discontinued)
</td>
<td>
@Html.ActionLink("Edit", "PutProduct", new {id=item.ProductID }) |
@Html.ActionLink("Details", "GetProductById",new{id=item.ProductID}) |
@Html.ActionLink("Delete", "DeleteProduct", new {id=item.ProductID})
</td>
</tr>
}
</table>
GetProductById.cshtml
@model Web_API.Models.Products
@{
ViewBag.Title = "GetProductById";
}
<h2>GetProductById</h2>
<fieldset>
<legend>Products</legend>
<div class="display-label">
@Html.DisplayNameFor(model => model.ProductID)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.ProductID)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.ProductName)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.ProductName)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.SupplierID)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.SupplierID)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.CategoryID)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.CategoryID)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.QuantityPerUnit)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.QuantityPerUnit)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.UnitPrice)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.UnitPrice)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.UnitsInStock)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.UnitsInStock)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.UnitsOnOrder)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.UnitsOnOrder)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.ReorderLevel)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.ReorderLevel)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.Discontinued)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.Discontinued)
</div>
</fieldset>
<p>
@Html.ActionLink("Edit", "Edit", new { /* id=Model.PrimaryKey */ }) |
@Html.ActionLink("Back to List", "Index")
</p>
PostProduct.cshtml
@model Web_API.Models.Products
@{
ViewBag.Title = "PostProduct";
}
<h2>PostProduct</h2>
@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
<legend>Products</legend>
@*<div class="editor-label">
@Html.LabelFor(model => model.ProductID)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ProductID)
@Html.ValidationMessageFor(model => model.ProductID)
</div>*@
<div class="editor-label">
@Html.LabelFor(model => model.ProductName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ProductName)
@Html.ValidationMessageFor(model => model.ProductName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.SupplierID)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.SupplierID)
@Html.ValidationMessageFor(model => model.SupplierID)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.CategoryID)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.CategoryID)
@Html.ValidationMessageFor(model => model.CategoryID)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.QuantityPerUnit)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.QuantityPerUnit)
@Html.ValidationMessageFor(model => model.QuantityPerUnit)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.UnitPrice)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.UnitPrice)
@Html.ValidationMessageFor(model => model.UnitPrice)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.UnitsInStock)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.UnitsInStock)
@Html.ValidationMessageFor(model => model.UnitsInStock)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.UnitsOnOrder)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.UnitsOnOrder)
@Html.ValidationMessageFor(model => model.UnitsOnOrder)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.ReorderLevel)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ReorderLevel)
@Html.ValidationMessageFor(model => model.ReorderLevel)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Discontinued)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Discontinued)
@Html.ValidationMessageFor(model => model.Discontinued)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
PutProduct.cshtml
注意:
多了一行程式碼
@Html.HiddenFor(model=>model.ProductID)
@model Web_API.Models.Products
@{
ViewBag.Title = "PutProduct";
}
<h2>PutProduct</h2>
@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
<legend>Products</legend>
<div class="editor-label">
@Html.LabelFor(model => model.ProductID)
</div>
<div class="editor-field">
@Html.DisplayFor(model => model.ProductID)
@Html.ValidationMessageFor(model => model.ProductID)
@Html.HiddenFor(model=>model.ProductID)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.ProductName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ProductName)
@Html.ValidationMessageFor(model => model.ProductName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.SupplierID)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.SupplierID)
@Html.ValidationMessageFor(model => model.SupplierID)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.CategoryID)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.CategoryID)
@Html.ValidationMessageFor(model => model.CategoryID)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.QuantityPerUnit)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.QuantityPerUnit)
@Html.ValidationMessageFor(model => model.QuantityPerUnit)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.UnitPrice)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.UnitPrice)
@Html.ValidationMessageFor(model => model.UnitPrice)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.UnitsInStock)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.UnitsInStock)
@Html.ValidationMessageFor(model => model.UnitsInStock)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.UnitsOnOrder)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.UnitsOnOrder)
@Html.ValidationMessageFor(model => model.UnitsOnOrder)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.ReorderLevel)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ReorderLevel)
@Html.ValidationMessageFor(model => model.ReorderLevel)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Discontinued)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Discontinued)
@Html.ValidationMessageFor(model => model.Discontinued)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
DeleteProduct.cshtml
@model Web_API.Models.Products
@{
ViewBag.Title = "DeleteProduct";
}
<h2>DeleteProduct</h2>
<h3>Are you sure you want to delete this?</h3>
<fieldset>
<legend>Products</legend>
<div class="display-label">
@Html.DisplayNameFor(model => model.ProductID)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.ProductID)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.ProductName)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.ProductName)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.SupplierID)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.SupplierID)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.CategoryID)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.CategoryID)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.QuantityPerUnit)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.QuantityPerUnit)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.UnitPrice)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.UnitPrice)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.UnitsInStock)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.UnitsInStock)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.UnitsOnOrder)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.UnitsOnOrder)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.ReorderLevel)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.ReorderLevel)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.Discontinued)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.Discontinued)
</div>
</fieldset>
@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
<p>
<input type="submit" value="Delete" /> |
@Html.ActionLink("Back to List", "Index")
</p>
}