Pergunta

Suponha que a seguinte rota:

{region}/{storehouse}/{controller}/{action}

Esses dois parâmetros region e storehouse No total, identifique uma única entidade - um Storehouse. Assim, um monte de controladores está sendo chamado no contexto de algum armazém. E eu gostaria de escrever ações como esta:

public ActionResult SomeAction(Storehouse storehouse, ...)

Aqui eu posso ler seus pensamentos: "Escreva um fichário personalizado, cara". Eu faço. No entanto, a questão é

Como evitar strings mágicos dentro do fichário de modelo personalizado?
Aqui está meu código atual:

public class StorehouseModelBinder : IModelBinder
{
    readonly IStorehouseRepository repository;
    public StorehouseModelBinder(IStorehouseRepository repository)
    {
        this.repository = repository;
    }

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var region = bindingContext.ValueProvider.GetValue("region").AttemptedValue;
        var storehouse = bindingContext.ValueProvider.GetValue("storehouse").AttemptedValue;
        return repository.GetByKey(region, storehouse);
    }
}

Se houve uma única chave, bindingContext.ModelName poderia ser usado...
Provavelmente, há outra maneira de fornecer todas as ações com um Storehouse objeto, ou seja, declarando -o como uma propriedade do controlador e preenchendo -o no Controller.Initialize.

Foi útil?

Solução

Acabei com outra abordagem. A ligação do modelo não é um mecanismo apropriado para o meu propósito. Filtro de ação é o caminho a seguir!

Os nomes não são os mesmos da pergunta, mas tratam o site como armazém.

public class ProvideCurrentSiteFilter: IActionFilter
{
    readonly ISiteContext siteContext;

    public ProvideCurrentSiteFilter(ISiteContext siteContext)
    {
        this.siteContext = siteContext;
    }

    void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext)
    {
    }

    void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.ActionParameters["currentSite"] = siteContext.CurrentSite;
    }
}

ISiteContext Análises de realização HttpContext.Current e puxa um objeto do repositório do site. Usando HttpContext.Current não é muito elegante, concordo. No entanto, tudo passa pelo COI, para que a testabilidade não sofra.

Há um atributo de filtro de ação nomeado ProvideCurrentSiteAttribute que usa ProvideCurrentSiteFilter. Então, meu método de ação se parece com isso:

[ProvideCurrentSite]
public ActionResult Menu(Site currentSite)
{
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top