有时候,向服务端请求一个实体,我们希望返回如下的格式:

links: [
    href: http://localhost:8901/api/user/diaries/2013-08-17,
    rel: "self",
    method: "GET",
    isTemplated: false
],
currentDate:"2013-08-17"

首先抽象出一个与Link相关的类:

public class LinkModel
{public stirng Href{get;set;}public stirng Rel{get;set;}public string Method{get;set;}public bool IsTemplated{get;set;}
}

再放到某个视图模型中:

public class DiaryModel
{//存储和模型相关的链接public ICollection<LinkModel> Links{get;set;}public DateTime CurrentDate{get;set;}
}public class Diary
{public int Id{get;set;}public DateTime CurrentDate{get;set;}
}

ModelFactory用来实现视图模型和领域模型之间的转化。

public class ModelFactory
{private UrlHelper _urlHelper;public ModelFactory(HttpRequestMessage request){_urlHelper = new UrlHelper(request);}//领域模型转换成视图模型public DiaryModel Create(Diary d){return new DiaryModel(){Links = new List<LinkModel>{CreateLink(_urlHelper.Link("Diaryis", new {diaryid=d.CurrentDate.ToString("yyyy-MM-dd")}),"self");},CurrentDate = d.CurrentDate}}public LinkModel CreateLink(string href, string rel, string method = "GET", bool isTemplated = false){return new LinkModel(){Href = href,Rel = rel,Method = method,IsTemplated = isTemplated}}//视图模型转换成领域模型public Diary Parse(DiaryModel model){try{var entity = new Diary();var selfLink = model.Links.Where(l => l.Rel == "self").FirstOrDefault();if(selfLink != null && !string.IsNullOrWhiteSpace(selfLink.Href)){//从Uri中取出主键var uri = new Uri(selfLink.Href);entity.Id = int.Parse(uri.Segments.Last());}entity.CurrentDate = model.CurrentDate;return entity;}catch(Exception ex){}}
}

Diaries这个controller略,路由方面:

//api/user/diaries
//api/user/diaries/2001-01-01
config.Routes.MapHttpRoute(name: "Diaries",routeTemplate: "api/user/diaries/{dairyid}",defaults: new {controller="diaries", diaryid=RouteParameter.Optional}
)

这样,在客户端发出 http://localhost:8901/api/user/diaries/2013-08-17 GET请求,得到如下的响应:

links: [
    href: http://localhost:8901/api/user/diaries/2013-08-17,
    rel: "self",
    method: "GET",
    isTemplated: false
],
currentDate:"2013-08-17"

在返回分页相关的action中,也可以返回相关的Link部分。

先定义一个基类控制器:

public abstract class BaseController : ApiController
{ICountingKsRepository _repo;ModelFactory _modelFactory;public BaseController(ICountingKsRepository repo){_repo = repo;//写在构造函数里的话有点迟,必须等实例化_modelFactory才有值//_modelFactory = new ModelFactory(this.Request);
    }protected ModelFactory TheModelFactory{get{if(_modelFactory == null){_modelFactory = new ModelFactory(this.Request, TheRepository);}return _modelFactory;}}protected ICountingsRepository TheRepoisitory{get{return _repo;}}
}

可见,把共同的部分封装到基类控制器中是很好的习惯,然后基类控制器的子类通过属性获取一些方面。

再到具体的控制器:

public class FoodsController : BaseController
{ICountingKsRepoisotry _repo;ModelFactory _modelFactory;public FoodsController(ICountingKsRepository repo) : base(repo){}const int PAGE_SIZE = 50;public object Get(bool includeMeasures = true, int page = 0){IQueryable<Food> query;if(includeMeausres){query = TheRepository.GetAllFoodsWithMeausres();}else{query = TheRepository.GetAllFoods();}//方便统计总数var baseQuery = query.OrderBy(f =>f.Description);//using System.Web.Http.Routingvar helper = new UrlHelper(Request);var links = new List<LinkModel>();if(page > 0){links.Add(TheModelFactory.CreateLink(helper.Link("Food", new {page = page - 1},"prevPage"));}if(page < totalPages - 1){links.Add(TheModelFactory.CreateLink(helper.Link("Food", new {page = page + 1},"nextPage"));}//把上一页和下一页的url保存下来//var prevUrl = page > 0 ? helper.Link("Food", new {page = page - 1}) : "";//var nextUrl = page > 0 ? helper.Link("Food", new {page  = page + 1}) : "";//输出总数var totalCount = baseQuery.Count();var totalPages = Math.Ceiling((double)totalCount/PAGE_SIZE);var result = baseQuery.Skip(PAGE_SIZE * page).Take(PAGE_SIZE).ToList().Select(f => TheModelFactory.FoodFromDomainToView(f));//方便客户端接收return new{TotalCount = totalCount,TotalPages = totalPages,Result = result,Links = links//PrevPageUrl = prevUrl,//NextPageUrl = nextUrl,
        }}public FoodModel Get(int foodid){return TheModelFactory.FoodFromDomainToView(TheRepository.GetFood(foodid));}
}

客户端请求:localhost:8901/api/nutrition/foods

{
    totalCount:800,
    totalPages:151,
    links: [
        {
            href: http://localhost:8901/api/nutrition/foods?page=1,
            rel: "prevPage",
            method: "GET",
            isTemplated: false,
        },
        {
            href: http://localhost:8901/api/nutrition/foods?page=2,
            rel: "nextPage",
            method: "GET",
            isTemplated: false
        }
    ],
    result: [...]
}

另外,还可以控制序列化过程。

在LinkModel这个视图中:

public class LinkModel
{public stirng Href{get;set;}public stirng Rel{get;set;}public string Method{get;set;}public bool IsTemplated{get;set;}
}

在显示的时候,可能不想让IsTemplated显示出来,如何在序列化的过程中做到呢?

--通过jsonFormatter.SerializerSettings.Converts属性,用来控制序列化为json数据时的显示方式。

在WebApiConfig.cs中:

var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().FirstOrDefault();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNameContractResolver();
jsonFormatter.SerializerSettings.Converts(new LinkModelConverter());

而LinkModelConverter类需要继承JsonConverter类。

public class LinkModelConverter : JsonConverter
{public override bool CanConvert(Type objectType){return objectType.Equals(typeof(LinkModel));}public override object ReadJson(JsonReader reader, Type object){return reader.Value;}public override void WriteJson(JsonWriter wrtier, object value){var model = value as LinkModel;if(model != null){wirter.WriteStartObject();writer.WirteProeprtyName("href");writer.WriteValue(model.Href);writer.WriteProeprtyName("rel");writer.WriteValue(model.Rel);if(!model.Method.Equals("GET",StringComparison.ordinalIgnoreCase)){writer.WritePropertyName("method");writer.WriteValue(model.Method);}if(model.IsTemplated){writer.WriterPropertyName("isTemplated");writer.WriteValue(model.IsTemplated);}writer.WriteEndObject();}}
}

转载于:https://www.cnblogs.com/darrenji/p/5144162.html

ASP.NET Web API中展示实体Link相关的方面相关推荐

  1. 利用查询条件对象,在Asp.net Web API中实现对业务数据的分页查询处理

    在Asp.net Web API中,对业务数据的分页查询处理是一个非常常见的接口,我们需要在查询条件对象中,定义好相应业务的查询参数,排序信息,请求记录数和每页大小信息等内容,根据这些查询信息,我们在 ...

  2. (四)Asp.net web api中的坑-【api的返回值】

    (四)Asp.net web api中的坑-[api的返回值] 原文:(四)Asp.net web api中的坑-[api的返回值] void无返回值 IHttpActionResult HttpRe ...

  3. ASP.NET Web API中的参数绑定总结

    ASP.NET Web API中的action参数类型可以分为简单类型和复杂类型. HttpResponseMessage Put(int id, Product item) id是int类型,是简单 ...

  4. 【ASP.NET Web API教程】5.5 ASP.NET Web API中的HTTP Cookie

    5.5 HTTP Cookies in ASP.NET Web API 5.5 ASP.NET Web API中的HTTP Cookie 本文引自:http://www.asp.net/web-api ...

  5. ASP.NET Web API中的Controller

    虽然通过Visual Studio向导在ASP.NET Web API项目中创建的 Controller类型默认派生与抽象类型ApiController,但是ASP.NET Web API框架本身只要 ...

  6. ASP.NET Web API中实现版本

    一般来说,api 接口是提供给其他系统或是其他公司使用,不能随意频繁的变更.然而,需求和业务不断变化,接口和参数也会发生相应的变化.如果直接对原来的接口进行修改,势必会影响线其他系统的正常运行.这就必 ...

  7. 监控系统简介(二):使用 App Metrics 在 ASP.NET Web API 中记录指标

    回顾 在<监控系统简介:使用 Prometheus 与 Grafana>一文中,我们了解了什么是监控系统,Prometheus 这一监控工具及它提供的数据类型.PromQL 以及 Graf ...

  8. ASP.NET Web API中实现版本的几种方式

    在ASP.NET Web API中,当我们的API发生改变,就涉及到版本问题了.如何实现API的版本呢? 1.通过路由设置版本 最简单的一种方式是通过路由设置,不同的路由,不同的版本,不同的contr ...

  9. 在ASP.NET Web API中使用OData的Action和Function

    本篇体验OData的Action和Function功能.上下文信息参考"ASP.NET Web API基于OData的增删改查,以及处理实体间关系".在本文之前,我存在的疑惑包括: ...

最新文章

  1. 使用Crypto++的AES GCM对称加密
  2. 【Error】InterfaceError (0, '')
  3. 如何从PostgreSQL json中提取数组
  4. Apache ZooKeeper - JMX监控 ZooKeeper 的运行状态
  5. 【密码学】CSP的概念
  6. 解决IDEA修改已有项目为maven项目时目录结构被改变的问题
  7. [GPL]GREP - basic - practice -advanced
  8. 给键盘上的enter设置事件_Selenium3 + Python3自动化测试系列——鼠标事件和键盘事件...
  9. docker kali安装mysql_Linux环境使用Docker安装MySql
  10. 20165230 2017-2018-2 《Java程序设计》第8周学习总结
  11. 【招聘】搜狗输入法-自然语言处理研究员
  12. 完成端口————留着看
  13. Vue.js 5 @慕课网
  14. 【算法笔记】扩展kmp算法(exkmp)
  15. Java 技术书籍大全
  16. java安卓屏幕护眼效果好_当前安卓机自带的护眼模式,比护眼大师的好嘛?
  17. 华为云账号登录流程和方法
  18. Git版本控制管理——远程版本库
  19. POJ1287 (最小生成树) 中文版
  20. python爬虫登录微博_【新手学Python爬虫】微博网页PC端抓包分析和模拟登录

热门文章

  1. asp.net中上传图片并生成小图片,自动添加水印的代码 .
  2. js实现的简单模态对话框
  3. fcntl函数完成 set_fl()函数还有clr_fl()函数的封装
  4. STM32时钟树学习笔记
  5. “7th-place-solution-microsoft-malware-prediction”——kaggle微软恶意代码检测比赛第七名代码
  6. BUUCTF-Reverse:reverse2
  7. 忽略某些文件 —— Git 学习笔记 05
  8. 【密码学】一万字带您走进密码学的世界(下)
  9. Truffle合约交互 - WEB端对以太坊数据的读写
  10. IELE:区块链的一个新虚拟机