现在做网站用mvc越来越普及了,其好处就不说了,在这里只记录一些很多人都容易忽视的地方。

引用本地css和js文件的写法

这应该是最不受重视的地方,有同事也说我有点小题大作,但我觉得用mvc还是得有一个好习惯,对于维护那肯定是有帮助的。

首先是下面的代码(推荐写法)

  1. <link href="@Url.Content("~/content/style.css")" rel="stylesheet" type="text/css" />
  2. <script type="text/javascript" src="@Url.Content("~/scripts/jquery-1.9.1.min.js")"></script>

很少人会这样写,大多数人应该是这样

  1. <link href="/content/style.css" rel="stylesheet" type="text/css" />
  2. <script type="text/javascript" src="/scripts/jquery-1.9.1.min.js"></script>

有什么区别,推荐的写法会要多一点代码,我也发现很多人都喜欢能省就省,而且也会说渲染出来的html代码和第二种没啥区别。是的,但是如果部署成站点下的虚拟目录情况就不一样了,第二种写法可能就会给你带来灾难了,所以还是开始就勤快点吧,以后就不会痛苦了。

超链接的写法

推荐写法

  1. <a href="@Url.Action("index","home")">首页</a>

很多人会这样写

  1. <a href="/home/index">首页</a>

两者的区别还是在于维护,一旦改变了路由规则,那么第二种方式改起来还是头疼的,第一种方式就不需要作任何改动了。

模型验证

尽管mvc自带的验证方式已经有很多了,但是在开发过程中总会有一些特殊的地方。举例:用户的手机号为非必填项,如果用户填写了手机号则需验证其合法性。

  1. [Required]
  2. [RegularExpression(@"^1[3|4|5|8]\d{9}$")]
  3. public string Cellphone { get; set; }

上面的代码不能满足非必填项这个要求,最直接的办法就是这样写(先去掉上面的验证方式)

  1. public ActionResult Create(UserModel model)
  2. {
  3. if (ModelState.IsValid) {
  4. if (!string.IsNullOrEmpty(model.Cellphone) && !Regex.IsMatch(model.Cellphone, @"^1[3|4|5|8]\d{9}$")) {
  5. return View(model);
  6. }
  7. }
  8. }

这种方式总感觉很笨笨的,而且也不美观,职责也有点乱,验证规则也最好不应该出现在Controller中。怎么解决?很简单,往往很多人都忽略了CustomValidation

  1. [CustomValidation(typeof(ValidationUtil), "ValidateCellphone")]
  2. public string Cellphone { get; set; }

再定义一个验证类

  1. public static class ValidationUtil
  2. {
  3. public static ValidationResult ValidateCellphone(string cellphone)
  4. {
  5. if (!string.IsNullOrEmpty(cellphone) && !Regex.IsMatch(cellphone, @"^1[3|4|5|8]\d{9}$")) {
  6. return new ValidationResult("错误的手机号码。示例:13800000000");
  7. }
  8.  
  9. return ValidationResult.Success;
  10. }
  11. }

这样就可以在Controller中去掉那块难看的代码了,验证也可以集中维护了,代码也显得优雅一些了。当然还有其他的方式,就是在Model中实现IValidatableObject也可以达到效果。

模型绑定

当一个表单可能是维护多个模型时,我发现之前有同事是这样做的

  1. public ActionResult Create()
  2. {
  3. var domain = new DomainModel() {
  4. Name = Request.Form["domainName"],
  5. ...
  6. };
  7.  
  8. var channel = new ChannelModel() {
  9. Name = Request.Form["channelName"],
  10. ...
  11. };
  12. }

看上去有点丑陋还要写好多代码哦,而且模型变化,改动的代码还是蛮多的,其实mvc是支持绑定多个模型的,只需要这样写

  1. [HttpPost]
  2. public ActionResult Create([Bind(Prefix = "domain")]DomainModel domain, [Bind(Prefix = "channel")]ChannelModel channel)
  3. {
  4. }

前端代码只需要简单变动一下

  1. 域名:@Html.TextBox("domain.name", string.Empty)
  2. 频道名称:@Html.TextBox("channel.name", string.Empty)

这样就可以将元数据绑定到不同的模型上去了

其他细节点

对于Action的参数也尽量这样使用

  1. [HttpPost]
  2. public ActionResult Bandwidth(DateTime start, DateTime end, string serviceId)
  3. {
  4. }

而不是这样

  1. [HttpPost]
  2. public ActionResult Bandwidth()
  3. {
  4. DateTime start = DateTime.Parse(Request.Form["start"]);
  5. DateTime end = DateTime.Parse(Request.Form["end"]);
  6. string serviceId = Request.Form["serviceId"];
  7. }
  8.  
  9. [HttpPost]
  10. public ActionResult Bandwidth(FormCollection form)
  11. {
  12. DateTime start = DateTime.Parse(form.Get("start"));
  13. DateTime end = DateTime.Parse(form.Get("end"));
  14. string serviceId = form.Get("serviceId");
  15. }

mvc自带的json序列化功能比较弱,所以会引入第三方类库,这时会出现这样的用法

  1. return Content(JsonConvert.SerializeObject(data));

当然不建议这样使用,还是那个要素,不利于维护,推荐的做法就是覆写Json方法

  1. protected override JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
  2. {
  3. return new NewJsonResult {
  4. Data = data,
  5. ContentType = contentType,
  6. ContentEncoding = contentEncoding,
  7. JsonRequestBehavior = behavior
  8. };
  9. }
  10.  
  11. class NewJsonResult : JsonResult
  12. {
  13. public override void ExecuteResult(ControllerContext context)
  14. {
  15. context.MustNotNull("context");
  16.  
  17. if (JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
  18. String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) {
  19. throw new InvalidOperationException("若要允许 GET 请求,请将 JsonRequestBehavior 设置为 AllowGet。");
  20. }
  21.  
  22. HttpResponseBase response = context.HttpContext.Response;
  23.  
  24. if (!String.IsNullOrEmpty(ContentType)) {
  25. response.ContentType = ContentType;
  26. }
  27. else {
  28. response.ContentType = "application/json";
  29. }
  30.  
  31. if (ContentEncoding != null) {
  32. response.ContentEncoding = ContentEncoding;
  33. }
  34. else {
  35. response.ContentEncoding = System.Text.Encoding.UTF8;
  36. }
  37.  
  38. if (Data != null) {
  39. response.Write(JsonConvert.SerializeObject(Data,
  40. new DataTableConverter(), new JavaScriptDateTimeConverter()));
  41. }
  42. }
  43. }

再配合过滤器,如将异常捕获统一写在OnException(ExceptionContext filterContext)中,操作日志写在OnActionExecuting(ActionExecutingContext filterContext)和OnActionExecuted(ActionExecutedContext filterContext)中,认证写在OnAuthorization(AuthorizationContext filterContext)中等等,经过一番考虑之后相信一个mvc项目变得可维护性就更高了,代码也整洁清爽,职责也比较明确。

暂时就想到这么多,后续再慢慢补充。总之要用好mvc是需要深入了解的,啃一下源码也是有收获的。欢迎大家补充。

[HttpPost]

asp.net mvc开发过程中的一些小细节的更多相关文章

  1. [2014-09-21]如何在 Asp.net Mvc 开发过程中更好的使用Enum

    场景描述 在web开发过程中,有时候需要根据Enum类型生成下拉菜单: 有时候在输出枚举类型的时候,又希望输出对应的更具描述性的字符串. 喜欢直接用中文的请无视本文 不多说,直接看代码. 以下代码借鉴 ...

  2. asp.net mvc route 中新发现的小技巧

    在发现这个小技巧之前,我经常被某些问题困扰,我们以博客园为例 1:是分类名称 2:是分类url 3:点击分类,进入的页面,要显示分类的名称 4:点击分类,进入的页面,要用分类相关参数 在日常web的开 ...

  3. asp.net MVC开发过程中,使用到的方法(内置方法及使用说明)

    ® 视图的返回使用案例: [HttpGet] [SupportFilter] public ActionResult UserTopic(string type, string TopPicId, s ...

  4. [转]在 ASP.NET MVC 4 中创建为移动设备优化的视图

    原文链接 https://msdn.microsoft.com/zh-cn/magazine/dn296507.aspx 如果深入探讨有关编写移动设备网站的常识性考虑因素,会发现其中有一种内在矛盾.  ...

  5. 【初学者指南】在ASP.NET MVC 5中创建GridView

    介绍 在这篇文章中,我们将会学习如何在 ASP.NET MVC 中创建一个 gridview,就像 ASP.NET Web 表单中的 gridview 一样.服务器端和客户端有许多可用的第三方库,这些 ...

  6. ASP.NET MVC 4中如何为不同的浏览器自适应布局和视图

    在ASP.NET MVC 4中,可以很简单地实现针对不同的浏览器自适应布局和视图.这个得归功于MVC中的"约定甚于配置"的设计理念. 默认的自适应 MVC 4自动地为移动设备浏览器 ...

  7. 在ASP.NET MVC环境中使用加密与解密

    在.NET Framework 4.5的NET框架中,在程序中加密与解密很方便.现在均学习ASP.NET MVC程序了,因此Insus.NET也在此写个学习的例子.在需要时可以参考与查阅. 写一个Ut ...

  8. 在 ASP.NET MVC 应用中使用 NInject 注入 ASMX 类型的 Web Service

    这几天,有同学问到为什么在 ASP.NET MVC 应用中,无法在 .ASMX 中使用 NInject 进行注入. 现象 比如,我们定义了一个接口,然后定义了一个实现. public interfac ...

  9. 在 ASP.NET MVC 项目中使用 WebForm、 HTML

    原文地址:http://www.cnblogs.com/snowdream/archive/2009/04/17/winforms-in-mvc.html ASP.NET MVC和WebForm各有各 ...

随机推荐

  1. 用归并排序或树状数组求逆序对数量 poj2299

    题目链接:https://vjudge.net/problem/POJ-2299 推荐讲解树状数组的博客:https://blog.csdn.net/int64ago/article/details/ ...

  2. 2018 宁夏省赛 F. Moving On

    题目链接 https://nanti.jisuanke.com/t/28406 大意是 有n(<=200)个城市,城市间有路(Input给了邻接矩阵)  每个城市有一个危险值,然后是q(2e4) ...

  3. spring入门——applicationContext与BeanFactory的区别

    我们知道从applicationContext容器对象中如何获取Bean了,其实spring框架还有另外一种获取bean的方法:BeanFactory代码如下: BeanFactory factory ...

  4. 为什么Firefox在SSH上这么慢?

    为什么Firefox在SSH上这么慢? Modified on: Fri, 13 Jul 2018 18:37:30 +0800 我尝试使用 通过SSH启动Firefox ssh -X user@ho ...

  5. 探索未知种族之osg类生物---呼吸分解之渲染遍历一

    总结 前面我们基本上已经完成对ViewerBase::frame()函数的探究,只剩下renderingTraversals()渲染遍历的探究,虽然就剩下了一个函数,但是这却是最重要的,不可少的一个步 ...

  6. 线程属性 pthread_attr_t

    参考资料: https://blog.csdn.net/hudashi/article/details/7709413 Posix线程中的线程属性pthread_attr_t主要包括scope属性.d ...

  7. docker容器的使用

    Docker客户端 docker客户端非常简单,我们可以直接输入docker命令来查看到Docker客户端的所有命令选项. runoob@ docker 可以通过命令docker command -- ...

  8. service redis start

    注意:需在redis-server所在目录执行

  9. ABP Xunit单元测试 第五篇

    1.创建如下的项目结构 public class TestName { public bool ValidateName(string Name) { if (Name == "yin&qu ...

  10. IDEA下Spring Boot显示Run Dashboard面板

    在 .idea/workspace.xml 文件中找到 <component name="RunDashboard"> <option name="ru ...