ASP.NET MVC com Spring.NET e ModelBinder
-
29-08-2019 - |
Pergunta
Eu estou trabalhando em uma demo que faz uso da capacidade Spring.NET COI em ASP.NET MVC. É como o tipo de aplicação MyBlog apresentado em par programação vídeo tutorial sobre www.asp.net site. Eu completei a mesma demonstração usando a estrutura Unidade da Microsoft e agora quer experimentar o container Spring. Para esse fim Eu tenho implementado um IControllerFactory simples que primeiro cria a fábrica de objeto Primavera assim:
IObjectFactory factory;
(....)
factory = new XmlObjectFactory(new FileSystemResource(application.Server.MapPath("objects.xml")))
e ao lado fica o controlador daquela fábrica assim:
public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName) {
IController result = context.GetObject(controllerName) as IController;
return result;
}
(manipulação de erro despojado para fins de simplificação).
Agora, em algum lugar na minha HomeController eu tenho esse tipo de ação:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AddEntry([Bind] BlogEntry entry, int id) {
entry.EntryDate = DateTime.Now;
....
E aqui está a parte de vista AddEntry.aspx que define os editores para o parâmetro de entrada (coisas realmente básico):
<form method="post" action="/Home/AddEntry/<%= ViewData["id"] %>">
<table>
<tr>
<td><label for="Title">Title</label></td>
<td><input name="entry.Title" type="text"/></td>
</tr>
<tr>
<td><label for="Text">Content</label></td>
<td><input name="entry.Text" type="text"/></td>
</tr>
</table>
<br />
<input type="submit" value="Add entry" />
<input type="button" value="Cancel" onclick="history.back(-1);" />
</form>
Agora, aqui está o negócio: Quando eu estou usando a Unidade IoC ele funciona como um encanto. parâmetro "entrada" fica desserializado a partir de minha forma como deveria e a linha
entry.EntryDate = DateTime.Now;
concluída sem problemas.
No entanto, quando eu mudar para Spring.NET fábrica de objeto (como descrito acima) as coisas começam a ir nozes. Primeiro de todos os parâmetros voltas "entrada" nulo assim uma exceção é lançada. Para rastrear o possível problema no meu fim Eu tenho implementado um tipo de IModelBinder personalizado que se parece com isso:
public class BlogEntryBinder : IModelBinder {
public ModelBinderResult BindModel(ModelBindingContext bindingContext) {
ModelBinderResult result = ModelBinders.DefaultBinder.BindModel(bindingContext);
return result;
}
}
Quando eu vim aqui usando a estrutura Unidade e detalhar bindingContext para HttpRequest vejo que o Request.HttpMethod é "POST" e Request.Form está devidamente preenchido. Quando eu fazer o mesmo usando Spring.NET o método é "GET" e Request.Form está vazio. Quando passo no entanto I à minha ação do controlador (addEntry) e detalhar o pedido em ambas as situações que eu vejo que o Request.HttpMethod e Request.Form têm seus valores apropriados.
Agora, a questão é como faço para corrigir a versão com Spring.NET para que ele funciona exatamente como a que utiliza estrutura Unidade?
Solução
Eu encontrei a resposta!
A minha definição de objeto parecia que:
<!-- Controlers -->
<object name="Home" type="MyBlog.Controllers.HomeController">
<property name="BlogService" ref="BlogService" />
<property name="BlogEntryService" ref="BlogEntryService" />
<property name="BlogEntryCommentService" ref="BlogEntryCommentService" />
</object>
Nevermind as propriedades sendo definido o que ele realmente faz é ele retorna a mesma instância cada vez que eu pedir para este objeto usando
IController result = context.GetObject(controllerName) as IController;
Então, quando eu mudei a definição de
<!-- Controlers -->
<object name="Home" type="MyBlog.Controllers.HomeController" singleton="false">
<property name="BlogService" ref="BlogService" />
<property name="BlogEntryService" ref="BlogEntryService" />
<property name="BlogEntryCommentService" ref="BlogEntryCommentService" />
</object>
tudo começou a trabalhar muito bem.
Com os melhores cumprimentos, Matthias.
Outras dicas
apenas uma nota adicional para esclarecer este comportamento: Controladores são tratados como protótipos pelo quadro ASP.NET MVC, mas o padrão de Primavera para o modo de Singleton. Portanto, você precisa marcar explicitamente o objeto como não-singleton na configuração recipiente. O próximo módulo de integração Spring MVC vai cuidar do presente, assim você não vai executar para esse então.
hth, Erich