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

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

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

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

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

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

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

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

超链接的写法

推荐写法

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

很多人会这样写

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

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

模型验证

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

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

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

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

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

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

再定义一个验证类

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

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

模型绑定

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

public ActionResult Create()
{
var domain = new DomainModel() {
Name = Request.Form["domainName"],
...
}; var channel = new ChannelModel() {
Name = Request.Form["channelName"],
...
};
}

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

[HttpPost]
public ActionResult Create([Bind(Prefix = "domain")]DomainModel domain, [Bind(Prefix = "channel")]ChannelModel channel)
{
}

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

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

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

其他细节点

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

[HttpPost]
public ActionResult Bandwidth(DateTime start, DateTime end, string serviceId)
{
}

而不是这样

[HttpPost]
public ActionResult Bandwidth()
{
DateTime start = DateTime.Parse(Request.Form["start"]);
DateTime end = DateTime.Parse(Request.Form["end"]);
string serviceId = Request.Form["serviceId"];
} [HttpPost]
public ActionResult Bandwidth(FormCollection form)
{
DateTime start = DateTime.Parse(form.Get("start"));
DateTime end = DateTime.Parse(form.Get("end"));
string serviceId = form.Get("serviceId");
}

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

return Content(JsonConvert.SerializeObject(data));

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

protected override JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)
{
return new NewJsonResult {
Data = data,
ContentType = contentType,
ContentEncoding = contentEncoding,
JsonRequestBehavior = behavior
};
} class NewJsonResult : JsonResult
{
public override void ExecuteResult(ControllerContext context)
{
context.MustNotNull("context"); if (JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) {
throw new InvalidOperationException("若要允许 GET 请求,请将 JsonRequestBehavior 设置为 AllowGet。");
} HttpResponseBase response = context.HttpContext.Response; if (!String.IsNullOrEmpty(ContentType)) {
response.ContentType = ContentType;
}
else {
response.ContentType = "application/json";
} if (ContentEncoding != null) {
response.ContentEncoding = ContentEncoding;
}
else {
response.ContentEncoding = System.Text.Encoding.UTF8;
} if (Data != null) {
response.Write(JsonConvert.SerializeObject(Data,
new DataTableConverter(), new JavaScriptDateTimeConverter()));
}
}
}

再配合过滤器,如将异常捕获统一写在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. [leetcode]366. Find Leaves of Binary Tree捡树叶

    Given a binary tree, collect a tree's nodes as if you were doing this: Collect and remove all leaves ...

  2. [leetcode]87. Scramble String字符串树形颠倒匹配

    Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...

  3. Java 基础之--注解Annotation详解

    自定义注解入门: public @interface Annotation01 { //set default value ""; String value() default & ...

  4. css3回顾 checkbox

    <div class="checkBox"> <input type="checkbox" id="check1"> ...

  5. Python开发——变量

    变量的作用 把程序运行的中间结果,临时保存到内存里,以备后面的代码继续调用 变量的声明 name = “yuan” 变量的定义规则 1.变量名只能是  字母.数字或下划线的任意组合 2.变量名的第一个 ...

  6. js 库

    plupload.full.min.js 前端上传利器 jQuery WeUI - V1.0.1 微信公众号开发利器

  7. js多维数组转一维数组

    1,使用map方法 var arr = [1,[2,[[3,4],5],6]]; function unid(arr){ var arr1 = (arr + '').split(',');//将数组转 ...

  8. AOP打印请求日志,打印返回值

    @Aspect // 申明是个spring管理的bean @Component @Slf4j public class LogAspectServiceApi { private JSONObject ...

  9. Scrum冲刺阶段1

    各个成员在 Alpha 阶段认领的任务 人员 任务 何承华 美化设计 部分后端设计 陈宇 后端设计 丁培辉 美化设计 部分后端设计 温志铭 前端设计 杨宇潇 服务器搭建 张主强 前端设计 明日各个成员 ...

  10. 【微信小程序开发】页面配置

    app下的app.json文件是全局配置. app下的每一个page中,也可以配置.json文件. page中配置的内容是对应app中window配置项下的内容. page中的配置将覆盖window中 ...