【发布时间】:2011-05-24 15:59:36
【问题描述】:
我们的 ASP.NET MVC 应用程序允许经过身份验证的用户管理与其帐户相关联的一个或多个“站点”。
我们的网址高度易于猜测,因为我们在网址中使用网站友好名称而不是 Id,例如:
/sites/mysite/
/sites/mysite/settings
/sites/mysite/blog/posts
/sites/mysite/pages/create
如您所见,我们需要在多个路由中访问站点名称。
我们需要对所有这些操作执行相同的行为:
- 在当前帐户中查找具有给定标识符的网站
- 如果返回的站点为 null,则返回 404(或自定义视图)
- 如果站点不为空(有效),我们可以继续执行操作
我们始终可以通过 ISiteContext 对象访问当前帐户。以下是我如何使用普通路由参数并直接在我的操作中执行查询来实现上述所有目标:
private readonly ISiteContext siteContext;
private readonly IRepository<Site> siteRepository;
public SitesController(ISiteContext siteContext, IRepository<Site> siteRepository)
{
this.siteContext = siteContext;
this.siteRepository = siteRepository;
}
[HttpGet]
public ActionResult Details(string id)
{
var site =
siteRepository.Get(
s => s.Account == siteContext.Account && s.SystemName == id
);
if (site == null)
return HttpNotFound();
return Content("Viewing details for site " + site.Name);
}
这还不错,但我需要在 20 个左右的操作方法上执行此操作,因此希望尽可能保持 DRY。
我对自定义模型绑定器的工作并不多,所以我想知道这是否是一份更适合他们的工作。一个关键要求是我可以将我的依赖项注入模型绑定器(对于 ISiteContext 和 IRepository - 如果需要,我可以回退到 DependencyResolver)。
非常感谢,
本
更新
以下是使用自定义模型绑定器和操作过滤器的工作代码。我仍然不确定我对此有何感想,因为
- 我应该从模型绑定器访问我的数据库
- 我可以实际上从动作过滤器中检索对象和空值验证。哪个更好?
模型绑定器:
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (!controllerContext.RouteData.Values.ContainsKey("siteid"))
return null;
var siteId = controllerContext.RouteData.GetRequiredString("siteid");
var site =
siteRepository.Get(
s => s.Account == siteContext.Account && s.SystemName == siteId
);
return site;
}
动作过滤器:
public class ValidateSiteAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var site = filterContext.ActionParameters["site"];
if (site == null || site.GetType() != typeof(Site))
filterContext.Result = new HttpNotFoundResult();
base.OnActionExecuting(filterContext);
}
}
控制器动作:
[HttpGet]
[ValidateSite]
public ActionResult Settings(Site site)
{
var blog = site.GetFeature<BlogFeature>();
var settings = settingsProvider.GetSettings<BlogSettings>(blog.Id);
return View(settings);
}
[HttpPost]
[ValidateSite]
[UnitOfWork]
public ActionResult Settings(Site site, BlogSettings settings)
{
if (ModelState.IsValid)
{
var blog = site.GetFeature<BlogFeature>();
settingsProvider.SaveSettings(settings, blog.Id);
return RedirectToAction("Settings");
}
return View(settings);
}
【问题讨论】:
标签: asp.net-mvc asp.net-mvc-3 modelbinders action-filter