ASP.NET MVC 2扩展点之Model Binder实例分析
MVC 2的Model可以是任意一个类。
许多教程只讲“ADO.NET实体数据模型”Model1.edmx
然后连接mssql2005以上,自动生成数据模型。
这样会让初学者不能更好地理解Model与View之间的关系。
这里我详细介绍一下怎样用任意一个类做Model,
这样你也可以在MVC项目中使用Access数据库,任意数据库吧。
步骤:新建MVC项目
删除默认生成的Controller,View,我喜欢简洁,突出重点。
右击Models目录,新建Book.cs
大气象
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MvcModelBinder.Models
{
public class Book
{
public string Title { get; set; }
public string Author { get; set; }
public DateTime DatePublished { get; set; }
}
}
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MvcModelBinder.Models
{
public class Book
{
public string Title { get; set; }
public string Author { get; set; }
public DateTime DatePublished { get; set; }
}
}
同上,新建BookModelBinder.cs,这样你就可以像“ADO.NET实体数据模型”使用任意类做Model了。
大气象
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;//IModelBinder命名空间
namespace MvcModelBinder.Models
{
public class BookModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var book = (Book)(bindingContext.Model ?? new Book());
book.Title = GetValue<string>(bindingContext, "Title");
book.Author = GetValue<string>(bindingContext, "Author");
book.DatePublished = GetValue<DateTime>(bindingContext, "DatePublished");
if (String.IsNullOrEmpty(book.Title))
{
bindingContext.ModelState.AddModelError("Title", "书名不能为空?");
}
return book;
}
private T GetValue<T>(ModelBindingContext bindingContext, string key)
{
ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(key);
bindingContext.ModelState.SetModelValue(key, valueResult);
return (T)valueResult.ConvertTo(typeof(T));
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;//IModelBinder命名空间
namespace MvcModelBinder.Models
{
public class BookModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var book = (Book)(bindingContext.Model ?? new Book());
book.Title = GetValue<string>(bindingContext, "Title");
book.Author = GetValue<string>(bindingContext, "Author");
book.DatePublished = GetValue<DateTime>(bindingContext, "DatePublished");
if (String.IsNullOrEmpty(book.Title))
{
bindingContext.ModelState.AddModelError("Title", "书名不能为空?");
}
return book;
}
private T GetValue<T>(ModelBindingContext bindingContext, string key)
{
ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(key);
bindingContext.ModelState.SetModelValue(key, valueResult);
return (T)valueResult.ConvertTo(typeof(T));
}
}
}
新建BookController.cs这里提交添加表单的时候,把数据保存在TempData中。
大气象
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcModelBinder.Models;
namespace MvcModelBinder.Controllers
{
public class BookController : Controller
{
#region 添加的代码
public ActionResult List()
{
List<Book> bookList = new List<Book>();
Book book = new Book();
book.Title = "书名";
book.Author = "作者";
book.DatePublished = DateTime.Now;
bookList.Add(book);
if (TempData["NewBook"] != null)
{
Book newBook = TempData["NewBook"] as Book;
bookList.Add(newBook);
}
return View(bookList);
}
//
// GET: /Book/Create
public ActionResult Create()
{
return View();
}
//
// POST: /Book/Create
[HttpPost]
public ActionResult Create(Book book)
{
try
{
// TODO: Add insert logic here
Book newBook = new Book();
newBook.Author = book.Author;
newBook.Title = book.Title;
newBook.DatePublished = book.DatePublished;
TempData["NewBook"] = book;
return RedirectToAction("List");
}
catch
{
return View();
}
}
#endregion
//
// GET: /Book/
public ActionResult Index()
{
return View();
}
//
// GET: /Book/Details/5
public ActionResult Details(int id)
{
return View();
}
//
// GET: /Book/Edit/5
public ActionResult Edit(int id)
{
return View();
}
//
// POST: /Book/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
try
{
// TODO: Add update logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
//
// GET: /Book/Delete/5
public ActionResult Delete(int id)
{
return View();
}
//
// POST: /Book/Delete/5
[HttpPost]
public ActionResult Delete(int id, FormCollection collection)
{
try
{
// TODO: Add delete logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcModelBinder.Models;
namespace MvcModelBinder.Controllers
{
public class BookController : Controller
{
#region 添加的代码
public ActionResult List()
{
List<Book> bookList = new List<Book>();
Book book = new Book();
book.Title = "书名";
book.Author = "作者";
book.DatePublished = DateTime.Now;
bookList.Add(book);
if (TempData["NewBook"] != null)
{
Book newBook = TempData["NewBook"] as Book;
bookList.Add(newBook);
}
return View(bookList);
}
//
// GET: /Book/Create
public ActionResult Create()
{
return View();
}
//
// POST: /Book/Create
[HttpPost]
public ActionResult Create(Book book)
{
try
{
// TODO: Add insert logic here
Book newBook = new Book();
newBook.Author = book.Author;
newBook.Title = book.Title;
newBook.DatePublished = book.DatePublished;
TempData["NewBook"] = book;
return RedirectToAction("List");
}
catch
{
return View();
}
}
#endregion
//
// GET: /Book/
public ActionResult Index()
{
return View();
}
//
// GET: /Book/Details/5
public ActionResult Details(int id)
{
return View();
}
//
// GET: /Book/Edit/5
public ActionResult Edit(int id)
{
return View();
}
//
// POST: /Book/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
try
{
// TODO: Add update logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
//
// GET: /Book/Delete/5
public ActionResult Delete(int id)
{
return View();
}
//
// POST: /Book/Delete/5
[HttpPost]
public ActionResult Delete(int id, FormCollection collection)
{
try
{
// TODO: Add delete logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
}
}
新建View:List.aspx,Create.aspx这里创建强类型视图,可以选择Book
Create.aspx
大气象
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<MvcModelBinder.Models.Book>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Create</title>
</head>
<body>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.Title) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Title) %>
<%: Html.ValidationMessageFor(model => model.Title) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Author) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Author) %>
<%: Html.ValidationMessageFor(model => model.Author) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.DatePublished) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.DatePublished) %>
<%: Html.ValidationMessageFor(model => model.DatePublished) %>
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Index") %>
</div>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Create</title>
</head>
<body>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.Title) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Title) %>
<%: Html.ValidationMessageFor(model => model.Title) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Author) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Author) %>
<%: Html.ValidationMessageFor(model => model.Author) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.DatePublished) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.DatePublished) %>
<%: Html.ValidationMessageFor(model => model.DatePublished) %>
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Index") %>
</div>
</body>
</html>
List.aspx
大气象
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MvcModelBinder.Models.Book>>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>List</title>
</head>
<body>
<table>
<tr>
<th></th>
<th>
Title
</th>
<th>
Author
</th>
<th>
DatePublished
</th>
</tr>
<% foreach (var item in Model) { %>
<tr>
<td>
<%: Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) %> |
<%: Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ })%> |
<%: Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })%>
</td>
<td>
<%: item.Title %>
</td>
<td>
<%: item.Author %>
</td>
<td>
<%: String.Format("{0:g}", item.DatePublished) %>
</td>
</tr>
<% } %>
</table>
<p>
<%: Html.ActionLink("Create New", "Create") %>
</p>
</body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>List</title>
</head>
<body>
<table>
<tr>
<th></th>
<th>
Title
</th>
<th>
Author
</th>
<th>
DatePublished
</th>
</tr>
<% foreach (var item in Model) { %>
<tr>
<td>
<%: Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) %> |
<%: Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ })%> |
<%: Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })%>
</td>
<td>
<%: item.Title %>
</td>
<td>
<%: item.Author %>
</td>
<td>
<%: String.Format("{0:g}", item.DatePublished) %>
</td>
</tr>
<% } %>
</table>
<p>
<%: Html.ActionLink("Create New", "Create") %>
</p>
</body>
</html>
最后据说需要在Global.asax中注册,我没有注册一样不出错。可能哪里理解不到位。
大气象
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using MvcModelBinder.Models;
namespace MvcModelBinder
{
// 注意: 有关启用 IIS6 或 IIS7 经典模式的说明,
// 请访问 http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // 路由名称
"{controller}/{action}/{id}", // 带有参数的 URL
new { controller = "Book", action = "List", id = UrlParameter.Optional } // 参数默认值
);
}
protected void Application_Start()
{
//据说需要这样注册一下,我不注册也不影响。不知道哪里理解不到位。
ModelBinders.Binders.Add(typeof(Book), new BookModelBinder());
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using MvcModelBinder.Models;
namespace MvcModelBinder
{
// 注意: 有关启用 IIS6 或 IIS7 经典模式的说明,
// 请访问 http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // 路由名称
"{controller}/{action}/{id}", // 带有参数的 URL
new { controller = "Book", action = "List", id = UrlParameter.Optional } // 参数默认值
);
}
protected void Application_Start()
{
//据说需要这样注册一下,我不注册也不影响。不知道哪里理解不到位。
ModelBinders.Binders.Add(typeof(Book), new BookModelBinder());
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
}
}
这是最终的目录结构:
本文源码:https://files.cnblogs.com/greatverve/MvcModelBinder.rar
这里这个大牛,不屑过多解释,这个工作由我来做吧。
我这个博客废弃不用了,今天想寻找外链的时候,突然想到这个博客权重很高。
有需要免费外链的,留言即可,我准备把这个博客变成免费的友情链接站点。