Vindê de modelo um objeto do repositório por várias chaves
-
25-09-2019 - |
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
.
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)
{
}