asp.net mvc开发过程中的一些小细节
现在做网站用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是需要深入了解的,啃一下源码也是有收获的。欢迎大家补充。
asp.net mvc开发过程中的一些小细节的更多相关文章
- [2014-09-21]如何在 Asp.net Mvc 开发过程中更好的使用Enum
场景描述 在web开发过程中,有时候需要根据Enum类型生成下拉菜单: 有时候在输出枚举类型的时候,又希望输出对应的更具描述性的字符串. 喜欢直接用中文的请无视本文 不多说,直接看代码. 以下代码借鉴 ...
- asp.net mvc route 中新发现的小技巧
在发现这个小技巧之前,我经常被某些问题困扰,我们以博客园为例 1:是分类名称 2:是分类url 3:点击分类,进入的页面,要显示分类的名称 4:点击分类,进入的页面,要用分类相关参数 在日常web的开 ...
- asp.net MVC开发过程中,使用到的方法(内置方法及使用说明)
® 视图的返回使用案例: [HttpGet] [SupportFilter] public ActionResult UserTopic(string type, string TopPicId, s ...
- [转]在 ASP.NET MVC 4 中创建为移动设备优化的视图
原文链接 https://msdn.microsoft.com/zh-cn/magazine/dn296507.aspx 如果深入探讨有关编写移动设备网站的常识性考虑因素,会发现其中有一种内在矛盾. ...
- 【初学者指南】在ASP.NET MVC 5中创建GridView
介绍 在这篇文章中,我们将会学习如何在 ASP.NET MVC 中创建一个 gridview,就像 ASP.NET Web 表单中的 gridview 一样.服务器端和客户端有许多可用的第三方库,这些 ...
- ASP.NET MVC 4中如何为不同的浏览器自适应布局和视图
在ASP.NET MVC 4中,可以很简单地实现针对不同的浏览器自适应布局和视图.这个得归功于MVC中的"约定甚于配置"的设计理念. 默认的自适应 MVC 4自动地为移动设备浏览器 ...
- 在ASP.NET MVC环境中使用加密与解密
在.NET Framework 4.5的NET框架中,在程序中加密与解密很方便.现在均学习ASP.NET MVC程序了,因此Insus.NET也在此写个学习的例子.在需要时可以参考与查阅. 写一个Ut ...
- 在 ASP.NET MVC 应用中使用 NInject 注入 ASMX 类型的 Web Service
这几天,有同学问到为什么在 ASP.NET MVC 应用中,无法在 .ASMX 中使用 NInject 进行注入. 现象 比如,我们定义了一个接口,然后定义了一个实现. public interfac ...
- 在 ASP.NET MVC 项目中使用 WebForm、 HTML
原文地址:http://www.cnblogs.com/snowdream/archive/2009/04/17/winforms-in-mvc.html ASP.NET MVC和WebForm各有各 ...
随机推荐
- [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 ...
- [leetcode]87. Scramble String字符串树形颠倒匹配
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...
- Java 基础之--注解Annotation详解
自定义注解入门: public @interface Annotation01 { //set default value ""; String value() default & ...
- css3回顾 checkbox
<div class="checkBox"> <input type="checkbox" id="check1"> ...
- Python开发——变量
变量的作用 把程序运行的中间结果,临时保存到内存里,以备后面的代码继续调用 变量的声明 name = “yuan” 变量的定义规则 1.变量名只能是 字母.数字或下划线的任意组合 2.变量名的第一个 ...
- js 库
plupload.full.min.js 前端上传利器 jQuery WeUI - V1.0.1 微信公众号开发利器
- js多维数组转一维数组
1,使用map方法 var arr = [1,[2,[[3,4],5],6]]; function unid(arr){ var arr1 = (arr + '').split(',');//将数组转 ...
- AOP打印请求日志,打印返回值
@Aspect // 申明是个spring管理的bean @Component @Slf4j public class LogAspectServiceApi { private JSONObject ...
- Scrum冲刺阶段1
各个成员在 Alpha 阶段认领的任务 人员 任务 何承华 美化设计 部分后端设计 陈宇 后端设计 丁培辉 美化设计 部分后端设计 温志铭 前端设计 杨宇潇 服务器搭建 张主强 前端设计 明日各个成员 ...
- 【微信小程序开发】页面配置
app下的app.json文件是全局配置. app下的每一个page中,也可以配置.json文件. page中配置的内容是对应app中window配置项下的内容. page中的配置将覆盖window中 ...