目录:
- Action返回类型
- 内容协商
一.Actio的返回类型
--四种类型
- void返回值
- IHttpActionResult
- HttpResponseMessage
- 自定义类型
返回类型 |
响应 |
void |
Return empty 204 (No Content) 返回无内容 |
HttpResponseMessage |
Convert directly to an HTTP response message. 直接转换为一个Http Reponse消息。 |
IHttpActionResult |
Call ExecuteAsync to create an HttpResponseMessage, then convert to an HTTP response message. 调用ExecuteAsync先创建一个HttpReponseMessage,在转换为Http Reponse输出。 |
其它类型 |
Write the serialized return value into the response body; return 200 (OK). 序列化后的信息返回到消息体中。 |
(1)void无返回值
实例 返回状态码204,没返回值
public class ORDER
{
public string ID { get; set; }
public string NO { get; set; }
public string NAME { get; set; }
}
public class OrderController : ApiController
{
[HttpPost]
public void SaveOrder(ORDER name)
{
//处理业务逻辑
}
}
$(function () {
$.ajax({
type: 'post',
url: 'http://localhost:21528/api/Order/SaveOrder',
data: { ID: "aaa", NAME: "test" },
success: function (data, status) {
alert(data);
}
});
});
(2)IHTTPActionResult
- json<T>(T content)
实例
[HttpGet]
public IHttpActionResult GetOrder()
{
var lstRes = new List<ORDER>();
lstRes.Add(new ORDER() { ID = "aaaa", NO = "111", NAME = "111" });
lstRes.Add(new ORDER() { ID = "bbbb", NO = "222", NAME = "222" });
return Json (lstRes);
}
//Json( )方法的返回类型JsonResult<T>,实现了IHttpActionResult接口。
$(function () {
$.ajax({
type: 'get',
url: 'http://localhost:
data: {},
success: function (data, status) {
alert(data);
}
});
});
- ok()、重载ok<T>(T content)
protected internal virtual OkResult Ok();
如果返回Ok(),就表示不向客户端返回任何信息,只告诉客户端请求成功。
[HttpGet]
public IHttpActionResult GetOKResult()
{
return Ok();
}
//重载ok
[HttpGet]
public IHttpActionResult GetOKResult(string name)
{
return Ok<string>(name);
}
注意:如果是返回实体或者实体集合,建议使用Json<T>(T content),如果是返回基础类型(如int、string等),使用Ok<T>(T content)
- NotFound()
NotFound()方法会返回一个404的错误到客户端。
- Content<T>()
[HttpGet]
public IHttpActionResult GetContentResult()
{
return Content<string>(HttpStatusCode.OK, "OK"); //向客户端返回值和http状态码。
}
- BadRequest()
[HttpGet]
public IHttpActionResult GetBadRequest(ORDER order)
{
if (string.IsNullOrEmpty(order.ID))
return BadRequest(); //向客户端返回400的HTTP错误
return Ok();
}
- Redirect(string location)
[HttpGet]
public IHttpActionResult RedirectResult()
{
return Redirect("http://localhost:21528/api/Order/GetContentResult"); //将请求重定向到其他地方。
}
- 自定义IHttpActionResult
namespace System.Web.Http
{
public interface IHttpActionResult //IHttpActionResult类型的定义
{ Task<System.Net.Http.HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken); }
//自定义一个bootstrapTable服务端分页的子类去展示自定义IHttpActionResult的用法。
public class PageResult : IHttpActionResult
{
object _value;
HttpRequestMessage _request;
public PageResult(object value, HttpRequestMessage request)
{
_value = value;
_request = request;
}
public Task<HttpResponseMessage> ExecuteAsync(System.Threading.CancellationToken cancellationToken)
{
var response = new HttpResponseMessage()
{
Content = new ObjectContent(typeof(object), _value, new JsonMediaTypeFormatter()),
RequestMessage = _request
};
return Task.FromResult(response);
}
}
//然后,在API接口里面返回PageResult对象。
[HttpGet]
public IHttpActionResult GetPageRow(int limit, int offset)
{
var lstRes = new List<ORDER>();
lstRes.Add(new ORDER() { ID = "aaaa", NO = "111", NAME = "111" });
lstRes.Add(new ORDER() { ID = "bbbb", NO = "222", NAME = "222" });
var oData = new { total = lstRes.Count, rows = lstRes.Skip(offset).Take(limit).ToList() };
return new PageResult(oData, Request);
}
(3).HttpResponMessage
//它表示向客户端返回一个http响应的消息对象(包含http状态码和需要返回客户端的消息)
public HttpResponseMessage Export()
{
//取数据
var lstRes = OrderBLL.Export();
//向Excel里面填充数据
HSSFWorkbook workbook = new HSSFWorkbook();
CreateAndFillSheet(workbook, lstRes);
//保存到服务
var fileName = "Excel" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xls";
var strPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Data" + fileName);
using (FileStream fs = new FileStream(strPath, FileMode.Create))
{
workbook.Write(fs);
using (MemoryStream ms = new MemoryStream())
{
workbook.Write(ms);
}
}
//输出到浏览器
try
{
var stream = new FileStream(strPath, FileMode.Open);
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(stream);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = fileName
};
return response;
}
catch
{
return new HttpResponseMessage(HttpStatusCode.NoContent);
}
}
//将文件流保存在StreamContent对象里面,然后输出到浏览器。在浏览器端即可将Excel输出。
(4).自定义类型
WebApi会自动序列化你自定义任何返回类型,然后将序列化的值写到响应正文里,状态码统一返回200。
[HttpGet]
public object GetOther()
{
var lstRes = new List<ORDER>();
lstRes.Add(new ORDER() { ID = "aaaa", NO = "111", NAME = "111"});
lstRes.Add(new ORDER() { ID = "bbbb", NO = "222", NAME = "222"});
return lstRes;
}
注意:对于一般接口的返回值,尽量使用IHttpActionResult类型作为返回值
二.内容协商
HTTP规范(RFC 2616)将内容协商定义为"在有多个表现可用时,为一个给定的响应选择最佳表现的过程"。在HTTP中内容协商的主要机制是以下请求报头:
Accept:响应可接收的媒体类型,如"application/json"、"application/xml",或者自定义媒体类型,如"application/vnd.example+xml"。
Accept-Charset:可接收的字符集,如"UTF-8"或"ISO 8859-1"。
Accept-Encoding:可接收的内容编码,如"gzip"。
Accept-Language:优先选用的自然语言,如"en-us"。
服务器也可以查看HTTP请求的其它选项。例如,如果该请求含有一个X-Requested-With报头,它指示这是一个AJAX请求,在没有Accept报头的情况下,服务器可能会默认使用JSON。
(1).序列化
//控制器动作
public Product GetProduct(int id)
{
var item = _products.FirstOrDefault(p => p.ID == id);
if (item == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return item;
}
//客户端可能会发送这样的HTTP请求:
GET http://localhost.:21069/api/products/1 HTTP/1.1
Host: localhost.:21069
Accept: application/json, text/javascript, */*; q=0.01
//服务器可能会发送一下相应
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 57
Connection: Close
{"Id":1,"Name":"Gizmo","Category":"Widgets","Price":1.99}
//客户端请求(指定)了JSON、Javascript、或"任意格式(*/*)"。服务器以一个Product对象的JSON表示作出了响应。
注意,响应中的Content-Type报头已被设置成"application/json"。
//控制器也可以返回一个HttpResponseMessage对象。为了指定响应体的CLR对象,要调用CreateResponse扩展方法:
public HttpResponseMessage GetProduct(int id)
{
var item = _products.FirstOrDefault(p => p.ID == id);
if (item == null)
{throw new HttpResponseException(HttpStatusCode.NotFound);}
return Request.CreateResponse(HttpStatusCode.OK, product);
}
//该选项让你能够对响应细节进行更多的控制。你可以设置状态码、添加HTTP报头等等
- 对资源进行序列化的对象叫做媒体格式化器。媒体格式化器派生于MediaTypeFormatter类。也可以创建自定义的格式化器,以支持其它媒体类型。
(2).内容协商的工作机制
- 工作过程分为三步:
- 管道从HttpConfiguration对象获取IContentNegotiator服务 。
- 从HttpConfiguration.Formatters集合中获取媒体格式化器列表 。
- 管道调用IContentNegotiatior.Negotiate(type,request,famatters)
- 参数是:要序列化的对象类型,Request对象,媒体格式化器的集合
- 返回结果:选用的格式化器,相应的媒体类型
Web API检测Request中Accept,Accept中有多种类型,从左到右,品质因子从高到低(默认q=1.0)并且同时尝试通过从格式化器列表中去找到一个匹配并且支持的媒体类。如果未找到格式化器,则Negotiate方法返回null,并且客户端接收HTTP错误406(不可接受)。