[转载]返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API
2012-12-14 14:18
519 查看
作者:webabcd
介绍 asp.net mvc 之 asp.net mvc 4.0 新特性之 Web API
开发一个 CRUD 的 Demo,服务端用 Web API,并使其支持 jsonp 协议,客户端用 jQuery
示例 1、自定义一个 JsonMediaTypeFormatter,以支持 jsonp 协议 MyJsonFormatter.cs
2、在 Global 中做的一些配置 Global.asax.cs
关于项目模版生成的代码的简短说明
web api 的路由配置 WebApiConfig.cs
3、提供 Web API 服务的 Controller(数据层用 Entity Framework 5.0 来实现) ProductsController.cs
4、调用 Web API 的客户端(用 jQuery 实现) CRUDDemo.cshtml
介绍 asp.net mvc 之 asp.net mvc 4.0 新特性之 Web API
开发一个 CRUD 的 Demo,服务端用 Web API,并使其支持 jsonp 协议,客户端用 jQuery
示例 1、自定义一个 JsonMediaTypeFormatter,以支持 jsonp 协议 MyJsonFormatter.cs
/* * 自定义一个 JsonMediaTypeFormatter,以支持 jsonp 协议 */ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Formatting; using System.Net.Http.Headers; using System.Threading.Tasks; using System.Web; namespace MVC40.Controllers { public class MyJsonFormatter : JsonMediaTypeFormatter { // jsonp 回调的函数名称 private string JsonpCallbackFunction; public MyJsonFormatter() { } public override bool CanWriteType(Type type) { return true; } // 每个请求都先来这里 public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, System.Net.Http.HttpRequestMessage request, MediaTypeHeaderValue mediaType) { var formatter = new MyJsonFormatter() { JsonpCallbackFunction = GetJsonCallbackFunction(request) }; // 增加一个转换器,以便枚举值与枚举名间的转换 formatter.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter()); // 增加一个转换器,以方便时间格式的序列化和饭序列化 var dateTimeConverter = new Newtonsoft.Json.Converters.IsoDateTimeConverter(); dateTimeConverter.DateTimeFormat = "yyyy-MM-dd HH:mm:ss"; formatter.SerializerSettings.Converters.Add(dateTimeConverter); // 排版返回的 json 数据,使其具有缩进格式,以方便裸眼查看 formatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented; return formatter; } // 序列化的实现 public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContent content, TransportContext transportContext) { if (string.IsNullOrEmpty(JsonpCallbackFunction)) return base.WriteToStreamAsync(type, value, stream, content, transportContext); StreamWriter writer = null; try { writer = new StreamWriter(stream); writer.Write(JsonpCallbackFunction + "("); writer.Flush(); } catch (Exception ex) { try { if (writer != null) writer.Dispose(); } catch { } var tcs = new TaskCompletionSource<object>(); tcs.SetException(ex); return tcs.Task; } return base.WriteToStreamAsync(type, value, stream, content, transportContext) .ContinueWith(innerTask => { if (innerTask.Status == TaskStatus.RanToCompletion) { writer.Write(")"); writer.Flush(); } }, TaskContinuationOptions.ExecuteSynchronously) .ContinueWith(innerTask => { writer.Dispose(); return innerTask; }, TaskContinuationOptions.ExecuteSynchronously) .Unwrap(); } // 从请求 url 中获取其参数 callback 的值 private string GetJsonCallbackFunction(HttpRequestMessage request) { if (request.Method != HttpMethod.Get) return null; var query = HttpUtility.ParseQueryString(request.RequestUri.Query); var queryVal = query["callback"]; if (string.IsNullOrEmpty(queryVal)) return null; return queryVal; } } }
2、在 Global 中做的一些配置 Global.asax.cs
using MVC40.Controllers; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http.Formatting; using System.Net.Http.Headers; using System.Web; using System.Web.Http; using System.Web.Mvc; using System.Web.Optimization; using System.Web.Routing; namespace MVC40 { public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); // 添加一个转换器 IsoDateTimeConverter,其用于日期数据的序列化和反序列化 var dateTimeConverter = new IsoDateTimeConverter(); dateTimeConverter.DateTimeFormat = "yyyy-MM-dd HH:mm:ss"; JsonSerializerSettings serializerSettings = new JsonSerializerSettings(); serializerSettings.Converters.Add(dateTimeConverter); // 清除全部 Formatter(默认有 4 个,分别是:JsonMediaTypeFormatter, XmlMediaTypeFormatter, FormUrlEncodedMediaTypeFormatter, JQueryMvcFormUrlEncodedFormatter) // GlobalConfiguration.Configuration.Formatters.Clear(); // 如果请求 header 中有 accept: text/html 则返回这个新建的 JsonMediaTypeFormatter 数据 var jsonFormatter = new JsonMediaTypeFormatter(); jsonFormatter.SerializerSettings = serializerSettings; // jsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); jsonFormatter.MediaTypeMappings.Add(new RequestHeaderMapping("accept", "text/html", StringComparison.InvariantCultureIgnoreCase, true, new MediaTypeHeaderValue("text/html"))); GlobalConfiguration.Configuration.Formatters.Insert(0, jsonFormatter); // 请求 url 中如果带有参数 xml=true,则返回 xml 数据 GlobalConfiguration.Configuration.Formatters.XmlFormatter.MediaTypeMappings.Add(new QueryStringMapping("xml", "true", "application/xml")); // 请求 url 中如果带有参数 jsonp=true,则返回支持 jsonp 协议的数据(具体实现参见 MyJsonFormatter.cs) MyJsonFormatter formatter = new MyJsonFormatter(); formatter.MediaTypeMappings.Add(new QueryStringMapping("jsonp", "true", "application/javascript")); GlobalConfiguration.Configuration.Formatters.Add(formatter); } } }
关于项目模版生成的代码的简短说明
<p> 项目模板更新了,原来堆在 Global.asax.cs 中的配置都分出去了 <br /> 在 App_Start 文件夹里自动生成的 BundleConfig.cs 用于对多个 css 或 js 做打包和压缩 <br /> 在 App_Start 文件夹里自动生成的 FilterConfig.cs 用于配置全局的 Action Filter <br /> 在 App_Start 文件夹里自动生成的 RouteConfig.cs 用于配置路由 <br /> 在 App_Start 文件夹里自动生成的 WebApiConfig.cs 用于为 web api 配置路由 </p>
web api 的路由配置 WebApiConfig.cs
/* * web api 的路由配置 */ using System; using System.Collections.Generic; using System.Linq; using System.Web.Http; namespace MVC40 { public static class WebApiConfig { public static void Register(HttpConfiguration config) { // 此配置为默认生成的配置 config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); // 由于默认为 web api 生成的路由配置,无 action 配置,所以只能通过 http 方法来匹配 action // 如果需要带 action 的路由则使用以下配置即可 /* routes.MapHttpRoute( name: "ActionApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); */ } } }
3、提供 Web API 服务的 Controller(数据层用 Entity Framework 5.0 来实现) ProductsController.cs
/* * ASP.NET Web API * * c - POST - 创建 * r - GET - 读取 * u - PUT - 更新 * d - DELETE - 删除 * * 注:win8 的 iis 默认不会安装 asp.net,需要在“程序和功能”中手动添加 */ using MVC40.Models; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Net; using System.Net.Http; using System.Threading.Tasks; using System.Web.Http; namespace MVC40.Controllers { /* * Web API 的 Controller 要从 ApiController 继承 * * 默认:http get 找 controller 的 get(), http post 找 controller 的 post(), http put 找 controller 的 put(), http delete 找 controller 的 delete() */ public class ProductsController : ApiController { // 获取全部 Product 数据:get http://localhost:17612/api/products public IEnumerable<Product> Get() { NorthwindEntities db = new NorthwindEntities(); var products = from p in db.Products orderby p.ProductID descending select p; return products.ToList(); } // 根据 ProductId 获取指定的 Product 数据:get http://localhost:17612/api/products/3 public Product Get(int id) { NorthwindEntities db = new NorthwindEntities(); var product = db.Products.SingleOrDefault(p => p.ProductID == id); return product; } // 新建 Product:post 一个 product 到 http://localhost:17612/api/products public void Post(Product product) { NorthwindEntities db = new NorthwindEntities(); db.Products.Add(product); db.SaveChanges(); } // 更新 Product:put 一个 product 到 http://localhost:17612/api/products public void Put(Product product) { NorthwindEntities db = new NorthwindEntities(); db.Products.Attach(product); var entry = db.Entry(product); entry.State = EntityState.Modified; db.SaveChanges(); } // 根据 ProductId 删除指定的 Product 数据:delete http://localhost:17612/api/products/3 public void Delete(int id) { NorthwindEntities db = new NorthwindEntities(); var product = db.Products.SingleOrDefault(p => p.ProductID == id); db.Products.Remove(product); db.SaveChanges(); } } }
4、调用 Web API 的客户端(用 jQuery 实现) CRUDDemo.cshtml
@{ Layout = null; } <!DOCTYPE html> <html> <head> <title>演示如何通过 jQuery 调用 asp.net web api 做 crud 操作</title> <script src="../Scripts/jquery-1.7.1.js" type="text/javascript"></script> </head> <body> <table id="tblProducts" border="1"> <tr> <th>Product Id</th> <th>Product Name</th> <th>Unit Price</th> <th>Actions</th> </tr> <tr> <td> <input type="text" id="txtProductId" size="5" disabled /></td> <td> <input type="text" id="txtProductName" /></td> <td> <input type="text" id="txtUnitPrice" /></td> <td> <input type="button" name="btnInsert" value="Insert" /></td> </tr> </table> <script type="text/javascript"> $(document).ready(function () { loadProductsAsync(); }); // 异步获取全部 Product 数据 function loadProductsAsync() { $.getJSON("/api/products?jsonp=true&callback=?", loadProductsCompleted).error(function () { alert('error') }); } // 显示获取到的 Product 数据 function loadProductsCompleted(data) { $("#tblProducts").find("tr:gt(1)").remove(); $.each(data, function (key, val) { var tableRow = '<tr>' + '<td>' + val.ProductID + '</td>' + '<td><input type="text" value="' + val.ProductName + '"/></td>' + '<td><input type="text" value="' + val.UnitPrice + '"/></td>' + '<td><input type="button" name="btnUpdate" value="Update" /> <input type="button" name="btnDelete" value="Delete" /></td>' + '</tr>'; $('#tblProducts').append(tableRow); }); $("input[name='btnInsert']").click(onInsert); $("input[name='btnUpdate']").click(onUpdate); $("input[name='btnDelete']").click(onDelete); } // 新增 Product 数据 function onInsert(evt) { var productName = $("#txtProductName").val(); var unitPrice = $("#txtUnitPrice").val(); // 构建需要 post 的数据,即需要添加的数据 var data = '{"ProductName":"' + productName + '","UnitPrice":' + unitPrice + '}'; $.ajax({ type: 'POST', url: '/api/products/', data: data, contentType: "application/json; charset=utf-8", dataType: 'json', success: function (results) { $("#txtProductName").val(''); $("#txtUnitPrice").val(''); alert('Product Added'); loadProductsAsync(); } }) } // 更新 Product 数据 function onUpdate(evt) { var productId = $(this).parent().parent().children().get(0).innerHTML; var cell = $(this).parent().parent().children().get(1); var productName = $(cell).find('input').val(); cell = $(this).parent().parent().children().get(2); var unitPrice = $(cell).find('input').val(); // 构建需要 put 的数据,即需要更新的数据 var data = '{"ProductID":"' + productId + '","ProductName":"' + productName + '","UnitPrice":' + unitPrice + '}'; $.ajax({ type: 'PUT', url: '/api/products/', data: data, contentType: "application/json; charset=utf-8", dataType: 'json', success: function (results) { alert('Product Updated'); } }) } // 删除指定的 Product 数据 function onDelete(evt) { var productId = $(this).parent().parent().children().get(0).innerHTML; $.ajax({ type: 'DELETE', url: '/api/products/' + productId, contentType: "application/json; charset=utf-8", dataType: 'json', success: function (results) { alert('Product Deleted'); loadProductsAsync(); } }) } </script> </body> </html>
相关文章推荐
- 【转载】返璞归真 asp.net mvc (11) - asp.net mvc 4.0 新特性之自宿主 Web API, 在 WebForm 中提供 Web API, 通过 Web API 上传文件, .net 4.5 带来的更方便的异步操作
- 返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API
- 返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API
- 返璞归真 asp.net mvc (11) - asp.net mvc 4.0 新特性之自宿主 Web API, 在 WebForm 中提供 Web API, 通过 Web API 上传文件, .net 4.5 带来的更方便的异步操作
- 返璞归真 asp.net mvc (11) - asp.net mvc 4.0 新特性之自宿主 Web API, 在 WebForm 中提供 Web API, 通过 Web API 上传文件, .ne
- 返璞归真 asp.net mvc (11) - asp.net mvc 4.0 新特性之自宿主 Web API, 在 WebForm 中提供 Web API, 通过 Web API 上传文件, .net 4.5 带来的更方便的异步操作
- 返璞归真 asp.net mvc (12) - asp.net mvc 4.0 新特性之移动特性
- 返璞归真 asp.net mvc (12) - asp.net mvc 4.0 新特性之移动特性
- 返璞归真 asp.net mvc (9) - asp.net mvc 3.0 新特性之 View(Razor)
- asp.net mvc 4.0 新特性之移动特性
- 返璞归真 asp.net mvc (7) - asp.net mvc 3.0 新特性之 Controller
- 返璞归真 asp.net mvc (6) - asp.net mvc 2.0 新特性
- 返璞归真 asp.net mvc (8) - asp.net mvc 3.0 新特性之 Model
- 3.ASP.NET MVC 3.0/4.0新特性
- 返璞归真 asp.net mvc (7) - asp.net mvc 3.0 新特性之 Controller
- 返璞归真 asp.net mvc (9) - asp.net mvc 3.0 新特性之 View(Razor)
- Asp.net MVC使用FormsAuthentication,MVC和WEB API可以共享身份认证 (转载)
- 返璞归真 asp.net mvc (6) - asp.net mvc 2.0 新特性 推荐
- ASP.NET MVC Web API 学习笔记---联系人增删改查 (转载)
- Asp.Net MVC 4.0【Web API】