young.han

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

现在做网站用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是需要深入了解的,啃一下源码也是有收获的。欢迎大家补充。

 

 

posted on 2014-12-03 10:31  young.han  阅读(2456)  评论(20编辑  收藏  举报