現在做網站用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是需要深入了解的,啃一下源碼也是有收獲的。歡迎大家補充。
複制去Google翻譯 翻譯結果 [ HttpPost ]
轉載于:https://www.cnblogs.com/younghan/p/4137207.html