现在做网站用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. Cobbler安装CentOS7系统时报错 What do you want do now?

    问题的根源: 在cobbler服务主机中执行了  createrepo --update  /var/www/cobbler/ks_mirror/CentOS-7-x86_64/ 导致的. cobbl ...

  2. 点击导出table表格

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  3. Powerdesigner数据库建模的浅谈

    1.建立新模型 2.创建物理数据模型(可以选择数据库类型及版本) 3.建立表 左键点击Table这个图标,鼠标移动到空白工作区,再左键,一个表的视图就出来了,(连续左键,会出现多个表的视图),右键退出 ...

  4. You are using pip version 9.0.1, however version 9.0.3 is available.

    1,pip不能用了,提示:You are using pip version 8.1.1, however version 9.0.1 is available.网上搜索了一箩筐的安装程序,各种安装, ...

  5. 【project】【Maven】dynamic web module 3.1 requires 1.7

    Maven导入和新建java web 项目时可能报的错. 解决方案: 1.保证 在eclipse 构建 web中关于java版本有三处需要修改统一:  右击项目,选择“propertie”===> ...

  6. SimpleDateFormat的parse(String str)方法的用法

    SimpleDateFormate 中的parse 方法可以将string类型的字符串转换成特定的date的特定类型.

  7. Java并发编程:volatile关键字

    volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以 ...

  8. springboot读取properties和yml配置文件

    一.新建maven工程:springboot-configfile-demo,完整工程如下: pom.xml <?xml version="1.0" encoding=&qu ...

  9. Python开发——3.基本数据类型之列表、元组和字典

    一.列表(list) 1.列表的格式 li = [11,22,"kobe",["lakers","ball",11],(11,22,),{& ...

  10. SQL STUFF函数 拼接字符串 多列 合并成一列 转

    关于和并列的 要这种效果. create table tb(idint, value varchar(10)) insert into tbvalues(1,'aa') insert into tbv ...