Bootstrap
这玩意我想很多人都知道,我就不多说了。有了它之后,我们程序员不需要美工也可以做出很漂亮的界面了,虽然我这个Demo没有很好看,但要是没有它那还真不知道要丑上多少倍。它还有中文版的站点: http://www.bootcss.com/
director.js
这是一个前端的route框架,什么叫前端route呢?大家如果去看我的那个Demo就会发现,URL并不是像某Q邮箱那样一直不变的,我们还是可以像以前那样每一个单一的功能一个URL。比如说:
- #/events/create
- #/events/all
- #/events/closed
- #/events/1
除了对用户比较友好之后,写代码的时候也会更加逻辑清晰,因为director会为每一个url绑定一个函数,就像mvc里面的action一样。当用户输入对应的url的时候,相应的函数就会被触发。
下面是来自官方首页的一个小小的例子,让你一眼就会用director。

requireJS
这玩意我也不用多介绍了吧,它具有延迟加载和避免重复加载的功能,来自官方的定义: requireJS是一个JavaScript文件和模块加载器。
knockout.js
这玩意就算我想给你介绍也不是三言两语就能说的清的,具体您还是参考源码吧。或者园子里面的大叔曾经翻译了官方的一个教程,有兴趣同学可以看看。 总之它是一个JavaScript的MVVM框架,当然这种框架有很多,backboneJS, breezeJS, Durandal,EmberJS,Angular 等等,我并没有全部了解过,所以我也不能告诉你他们的优势和缺点分别在哪里。选择knockout.js是因为之前了解过,好上手,然后以上这3种开源的框架全是基于MIT开源协议的,这样我们就可以用它做商业开发了。
用requireJS实现远程模板的调用
直接用require来加载html模板是不行的,人家已经说了是一个Javascript文件和模块的加载器。所以这里面我们需要用到requireJS的文本插件,这样我们就可以用它来加载文本了。https://github.com/requirejs/text
把那个text.js下载下来,直接放到我们程序的根目录下,然后我们就可以用像加载js一样的方法来加载html代码了,除了要在我们文件位置前面加上一个text! 之外。
|
1
2
3
|
require(['text!/template/createevent'], function (template) { // 你在这里就可以拿到模板了。}) |
rest中关于局部更新的讨论
我们常用的http verb有四种:

我们用PUT方式去更新的话,是将整个Model全部更新。当然你也可以换成下面这种方式,只更新你想要更新的字段。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
[HttpPut]public void Put(Event item){ var newItem = new Event(); newItem.Id = item.Id; // 在下面将你想要更新的值转到newItem下 newItem.Title = item.Title; if (!repository.Update(newItem)) { throw new HttpResponseException(HttpStatusCode.NotFound); }} |
注意:Put方式的URl只有一种(在我们不建其它route的情况下),也就是我们上面列出来的 /api/events/{id},然后将event对象作为body传过去。比如说在我们的demo中,我们有更新操作,还有像“关闭”这样的操作,我想这样的操作几乎在每一个系统里面都会遇到,这样的操作只会更新一个字段(在这里是“状态”列)。 那我怎么样再建一个Put方法去更改这一个字段呢?而且最好的方法是我只用传id过去就可以了。
通过google,我找到一个叫Patch的玩意, 它也是一种http verb,并且同样也是提供更新操作。但是与Put不一样的是Patch允许只将你需要更改的字段传到服务器端。
|
1
2
3
4
5
6
7
8
9
10
11
|
var obj = { Revision : "2"}; $.ajax({ url: 'api/values/1', type: 'PATCH', data: JSON.stringify(obj), dataType: 'json', contentType: 'application/json', success: function (data) { }}); |
但是不管怎么说,这种方式我是没有行通的,一旦我的实体对象加上一些验证的Attribute比如说Required之后,那些字段全都会被赋上默认值。 最后我不得不放弃了这种做法。
添加Route来创建两个PUT方法
另外一种做法,也就是我们Demo中实现的做法是增加了一个Route,在我们的web api中实现了两个put的方法。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
[Route("api/events/{id}/close")]public void Put(int id){var item = repository.Get(id);if (item == null){ throw new HttpResponseException(HttpStatusCode.NotFound);}item.Status = EventStatus.Closed;if (!repository.Update(item)){ throw new HttpResponseException(HttpStatusCode.NotFound);}} |
这样当我用PUT的方式提交到 api/events/3/close 的时候,我们的web api就会执行上面的方法然后把我们的event关闭了。
WEB API的验证
基本上任何系统都避免不了与验证打交道,除非那个系统压根不从用户那里获取数据。WEB API的验证方式大至相同,我们仍旧可以在我们的Model中采用Attribute的方式去声明验证条件。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class Event{public int Id { get; set; }[Required][MinLength(10)]public string Title { get; set; }public string Description { get; set; }public DateTime Start { get; set; }public DateTime End { get; set; }[Required]public string Owner { get; set; }public EventStatus Status { get; set; }} |
在api方法中我们用ModelState.IsValid判断就可以了。
|
1
2
3
4
5
6
7
8
9
10
11
12
|
public HttpResponseMessage Post(Event item){ if (ModelState.IsValid) { // 保存操作 return new HttpResponseMessage(HttpStatusCode.OK); } else { return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState); }} |
用AOP的方式去实现验证
或者我们可以换成下面的这种方式,先创建一个Filter。
|
1
2
3
4
5
6
7
8
9
10
11
|
public class ValidateModelAttribute : ActionFilterAttribute{ public override void OnActionExecuting(HttpActionContext actionContext) { if (!actionContext.ModelState.IsValid) { actionContext.Response = actionContext.Request.CreateErrorResponse( HttpStatusCode.BadRequest, actionContext.ModelState); } }} |
再到Post和PUT的方法上面打上这个标签。
|
1
2
3
4
5
6
7
8
9
|
[HttpPut][ValidateModel]public void Put(Event item){ if (!repository.Update(item)) { throw new HttpResponseException(HttpStatusCode.NotFound); }} |
我们还需要在我们的WebApiConfig中注册这个Filter。
|
1
2
3
4
5
6
7
|
public static class WebApiConfig{ public static void Register(HttpConfiguration config) { config.Filters.Add(new ValidateModelAttribute()); }} |

前端拿到这个消息之后,就可以通知给用户了。当然最后还是需要加上前端验证,可以大大的提高用户体验以及减轻服务器的压力。
浙公网安备 33010602011771号