系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html

题外话:由于这个技术点是新学的,并不属于原系列,但借助了原系列的项目背景,故命名外传系列,以后也可能在这个系列中附加一些新的技术。

前言

在Web Api 2.0中,提出了一种新的配置路由方式——基于特性的路由(Attribute-based Routing),在我们之前介绍的配置路由方式称为——基于公约的路由(Convention-based Routing),新的路由配置方式同样应用在MVC5中,因此本文就来介绍一下基于特性的路由。

在之前的一篇文章中,我们处理了这么一个业务——实现学生选课。我们是通过在“WebApiConfig”定制了一条路由数据来实现的,这条路由实现了选课以及根据课程Id来查询选择选择该课程的所有学生信息,感觉设计还可以。在实际应用中一般来说查询用的是最多的,使用Attribute Routing来注册路由会更灵活,控制起来也更方便,更符合Rest。本文以根据课程的名字来查询所有选择该课程的学生信息以及根据课程名字以及学生名字查询某一学生的信息。

基于特性的路由介绍

顾名思义,新路由将使用一个特性来实现路由注册,如下:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple=true, Inherited=true)]
public sealed class RouteAttribute : Attribute, IHttpRouteInfoProvider
{
public RouteAttribute();
public RouteAttribute(string template); public string Name { get; set; }
public int Order { get; set; }
public string Template { get; private set; }
}

这个类包含3个属性:Name指路由的名字,Order是指路由的顺序,Template就是我们要去匹配URL的模板

实现Attribute Routing

原理性的东西不多介绍的(我也没多研究 呵呵),能把学到的技术运用到实际中才是王道,上来一大堆原理容易晕,以后需要深入研究再看原理。

在“EnrollmentsController”中新增一个方法GetStudentsInfo:

[Route("api/enrollments/{courseName}/{studentName?}")]
public IEnumerable<StudentBaseModel> GetStudentsInfo(string courseName, string studentName="")
{
IQueryable<Student> query;
Course course= TheRepository.GetAllCourses().Where(c => c.Name == courseName).FirstOrDefault();
if (course==null )
{
return null ;
}
query = TheRepository.GetEnrolledStudentsInCourse(course.Id).OrderBy(s => s.LastName);
if (!string.IsNullOrWhiteSpace(studentName))
{
query = query.Where(s => s.FirstName == studentName);
}
var totalCount = query.Count(); System.Web.HttpContext.Current.Response.Headers.Add("X-InlineCount", totalCount.ToString()); var results = query .ToList()
.Select(s => TheModelFactory.Create(s)); return results; }

在我们的Action上使用了RouteAttribute。分析一下这个URL模板("api/enrollments/{courseName}/{studentName?}"),{courseName}会匹配到Action的courseName参数上,对于Action的另一个参数studentName是一个可选参数,也就是说请求中没有给出值那么就是默认的空字符串,有值得话就会被赋值,因此我们在“{studentName}”后面加上? 标记为可选的URI参数。

ok,就这么简单,测试一次:

结果:

呃,出错了。。。

一个新的问题

出错了,不过不管怎么说解决方案总归是有的,首先看下错误原因:是在LearningControllerSelector类的方法中出现了空引用,那么我们就不得不看下这个方法:

public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
var controllers = GetControllerMapping(); //Will ignore any controls in same name even if they are in different namepsace var routeData = request.GetRouteData(); var controllerName = routeData.Values["controller"].ToString(); HttpControllerDescriptor controllerDescriptor; if (controllers.TryGetValue(controllerName, out controllerDescriptor))
{ var version = ""; var versionedControllerName = string.Concat(controllerName, "V", version); HttpControllerDescriptor versionedControllerDescriptor;
if (controllers.TryGetValue(versionedControllerName, out versionedControllerDescriptor))
{
return versionedControllerDescriptor;
} return controllerDescriptor;
} return null; }

看了这段代码我们不难发现这个方法是我们重写了基类的方法,目的是为了实现现版本控制(详情可移步:http://www.cnblogs.com/fzrain/p/3558765.html),在我们重写的方法中我们用到了RouteData中包含的Controller的名字,而这个名字是由基于公约的路由与URI匹配得到的,因此我们这里肯定是没有的。因为我们的项目混合了2钟路由配置,而自定义的方法是针对基于公约的路由配置,因此对于Attribute Routing我们直接使用默认的选择方式:

在“var controllerName = routeData.Values["controller"].ToString(); ”代码之前加一个判断:

if (string.IsNullOrWhiteSpace(routeData.Route.RouteTemplate))
{
return base.SelectController(request);
}

再次请求就会得到如下结果:

结果正确,解决方案感觉还可以再考虑考虑,大家有什么好的建议可以提。但是不管怎么说,有一点是明确的:对于基于特性的路由规则,不需要包含Controller的名字,在本案列中感觉上是寻找Acton上的路由模板来匹配请求的URI,然后确定对应的Action。

总结

基于特性路由(Attribute Routing)是一种新的定制路由规则方式,与传统的配置方式相比更灵活,但同时比较分散,在web api中,2钟路由配置方式可以共存,所以本文只是介绍一种新的配置方式,做项目时也可以多一种选择。

本文参考相关链接:http://www.cnblogs.com/aehyok/p/3449851.html

http://www.cnblogs.com/artech/p/attribute-routing-01.html

源码地址:https://github.com/fzrain/WebApi.eLearning

使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【外传】——Attribute Routing的更多相关文章

  1. ASP.NET Web Api构建基于REST风格的服务实战系列教程

    使用ASP.NET Web Api构建基于REST风格的服务实战系列教程[十]——使用CacheCow和ETag缓存资源 系列导航地址http://www.cnblogs.com/fzrain/p/3 ...

  2. 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【开篇】【持续更新中。。。】

    最近发现web api很火,园内也有各种大神已经在研究,本人在asp.net官网上看到一个系列教程,原文地址:http://bitoftech.net/2013/11/25/detailed-tuto ...

  3. 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【九】——API变了,客户端怎么办?

    系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 一旦我们将API发布之后,消费者就会开始使用并和其他的一些数据混在一起.然而,当新的需求出现 ...

  4. 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【八】——Web Api的安全性

    系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 这一篇文章我们主要来探讨一下Web Api的安全性,到目前为止所有的请求都是走的Http协议 ...

  5. [转]使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【八】——Web Api的安全性

    本文转自:http://www.cnblogs.com/fzrain/p/3552423.html 系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html ...

  6. 使用ASP.NET WEB API构建基于REST风格的服务实战系列教程(一)——使用EF6构建数据库及模型

    系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 使用Entity Framework Code First模式构建数据库对象 已经决定使用EF C ...

  7. 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【二】——使用Repository模式构建数据库访问层

    系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 在数据访问层应用Repository模式来隔离对领域对象的细节操作是很有意义的.它位于映射层 ...

  8. 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【五】——在Web Api中实现Http方法(Put,Post,Delete)

    系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 在Web Api中,我们对资源的CRUD操作都是通过相应的Http方法来实现——Post(新 ...

  9. 使用ASP.NET Web Api构建基于REST风格的服务实战系列教程【三】——Web Api入门

    系列导航地址http://www.cnblogs.com/fzrain/p/3490137.html 前言 经过前2节的介绍,我们已经把数据访问层搭建好了,从本章开始就是Web Api部分了.在正式开 ...

随机推荐

  1. js 技巧和细节

    1. if中的各种变量返回值 一个值为 true 或者 false 的表达式.如果需要,非 Boolean 表达式也可以被转换为 Boolean 值,但是要遵循下列规则: 所有的对象都被当作 true ...

  2. pdo简单操作

    PDO(PHP Data Object) 是PHP 5新出来的东西,在PHP 6都要出来的时候,PHP 6只默认使用PDO来处理数据库,将把所有的数据库扩展移到了PECL,那么默认就是没有了我们喜爱的 ...

  3. RAP在centos上的部署

    在centos7上部署RAP(非官方) 作者批注:该部署文档为网友贡献,仅供参考.war请参考主页README.md下载最新版本哟~~~ 感谢热情网友的Wiki整理!万分感谢! 系统: centos7 ...

  4. 【OpenJ_POJ C16D】Extracurricular Sports(构造,找规律)

    题目求n个互不相同的数,满足其和为其lcm.我们把lcm看成一个线段,分割成长度不同的n份.当然分法有很多,我们只需要构造一个好想好写的.先分成两个二分之一,取其中一个二分之一再分成1/3和2/3,接 ...

  5. Day_6作业_模拟人生

    as #!/usr/bin/env python # encoding: utf-8 class wisdom(object): def __init__(self,n,g): self.n = n ...

  6. Leetcode 131. Palindrome Partitioning

    Given a string s, partition s such that every substring of the partition is a palindrome. Return all ...

  7. MapReduce实现数据去重

    一.原理分析 Mapreduce的处理过程,由于Mapreduce会在Map~reduce中,将重复的Key合并在一起,所以Mapreduce很容易就去除重复的行.Map无须做任何处理,设置Map中写 ...

  8. Linq Like

    Like的操作,有点像in,但是,方向变了.什么意思呢.就是你给定一个字符串,去寻找数据中某个字段包含这个字符串.就是给定的字符串是某字段的子集.Sql Script是这么写的. Selec * fr ...

  9. VS调试时同时启动多个项目解决方法

    选中要设置的项目,不要右击里面的属性,而是按f4时显示属性,下面总是在调试时启动设为false.

  10. 关于python

    1.from foo import bar 从foo中import bar,如果bar是一个数组,那么接下来你就可以在你当前程序中直接使用名为bar的这个数组. 2.import bar as foo ...