asp.net-mvc - 路由参数、自定义模型绑定(bind)器或操作过滤器?

标签 asp.net-mvc asp.net-mvc-3 modelbinders action-filter

我们的 ASP.NET MVC 应用程序允许经过身份验证的用户管理一个或多个链接到其帐户的“站点”。

我们的网址是 高度 可以猜测,因为我们在 URL 中使用站点友好名称而不是 Id,例如:

/sites/mysite/
/sites/mysite/settings

/sites/mysite/blog/posts
/sites/mysite/pages/create

如您所见,我们需要在多个路由中访问站点名称。

我们需要对所有这些操作执行相同的行为:
  • 上查找具有给定标识符的站点当前帐号
  • 如果返回的站点为空,则返回 404(或自定义 View )
  • 如果站点不为空(有效),我们可以继续执行操作

  • 当前帐户始终可以通过 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。

    我对自定义模型活页夹做的不多,所以我想知道这是否是一份更适合他们的工作。一个关键要求是我可以将我的依赖项注入(inject)模型绑定(bind)器(对于 ISiteContext 和 IRepository - 如果需要,我可以回退到 DependencyResolver)。

    非常感谢,



    更新

    下面是使用自定义模型绑定(bind)器和操作过滤器的工作代码。我仍然不确定我对此有何感想,因为
  • 我是否应该从模型绑定(bind)器访问我的数据库
  • 实际上,我可以从 Action 过滤器中检索对象和进行 null 验证。哪个更好?

  • 模型粘合剂:
    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;
    }
    

    Action 过滤器:
    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);
        }
    }
    

    Controller Action :
    [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);
    }
    

    最佳答案

    这个绝对听起来像是 Action 过滤器的工作。您可以使用 Action 过滤器进行 DI,这不是问题。

    所以,是的,只需将您现有的功能转换为 Action 过滤器,然后将其应用于每个 Action 或 Controller 或您继承的基本 Controller 。

    我不太清楚您的网站是如何工作的,但您可以使用全局操作过滤器来检查特定路由值的存在,例如'站点名称'。如果存在该路由值,则意味着您需要检查该站点是否存在...

    关于asp.net-mvc - 路由参数、自定义模型绑定(bind)器或操作过滤器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6113303/

    相关文章:

    c# - 在 MVC C# 中关闭了 html 条件编译

    c# - 尝试使用 webgrid 对 Controller 进行单元测试时,HttpContext 为空

    asp.net-mvc - ASP.NET MVC - 混合自定义和默认模型绑定(bind)

    .net - 在绑定(bind)之前使用 MVC ModelBinders 过滤帖子值

    javascript - 模态错误 - 未捕获的 TypeError : undefined is not a function modal

    javascript - 使用 Asp.net web api 下载时出错

    c# - ASP.NET MVC Controller 生命周期

    javascript - 将哈希表 {} 从 javascript 传递到 mvc3 Controller ?

    nunit - 单元测试时模型不会自动验证

    asp.net-mvc - 复杂复合对象的自定义模型绑定(bind)器帮助