ASP.NET MVC с Spring.NET и ModelBinder - PullRequest
3 голосов
/ 30 декабря 2008

Я работаю над демонстрацией, которая использует возможности Spring.NET IoC в ASP.NET MVC. Это похоже на приложение MyBlog, представленное в видеоурок по парному программированию на сайте www.asp.net. Я завершил ту же самую демонстрацию, используя Microsoft Unity Framework, и теперь хочу попробовать контейнер Spring. С этой целью я реализовал простую IControllerFactory, которая сначала создает фабрику объектов Spring следующим образом:

IObjectFactory factory;
(....)
factory = new XmlObjectFactory(new FileSystemResource(application.Server.MapPath("objects.xml")))

и затем он получает контроллер с этой фабрики так:

public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName) {
    IController result = context.GetObject(controllerName) as IController;
    return result;
}

(обработка ошибок исключена для упрощения).

Теперь где-то в моем HomeController у меня есть такое действие:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AddEntry([Bind] BlogEntry entry, int id) {
    entry.EntryDate = DateTime.Now;
....

А вот часть представления AddEntry.aspx, которая определяет редакторы для параметра ввода (действительно базовые вещи):

<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>

Теперь вот сделка: Когда я использую Unity IoC, это работает как шарм. Параметр "entry" десериализуется из моей формы, как и должно быть, и строка

entry.EntryDate = DateTime.Now; 

завершается без проблем.

Однако, когда я переключаюсь на фабрику объектов Spring.NET (как описано выше), все начинает сходить с ума. Прежде всего, параметр «запись» обнуляется, поэтому генерируется исключение. Чтобы отследить возможную проблему с моей стороны, я реализовал своего рода IModelBinder, который выглядит следующим образом:

public class BlogEntryBinder : IModelBinder {
    public ModelBinderResult BindModel(ModelBindingContext bindingContext) {
        ModelBinderResult result = ModelBinders.DefaultBinder.BindModel(bindingContext);
        return result;
    }
}

Когда я прихожу сюда, используя инфраструктуру Unity и углубляясь от bindingContext до HttpRequest, я вижу, что Request.HttpMethod имеет значение «POST» и Request.Form заполнен правильно. Когда я делаю то же самое с помощью Spring.NET, метод "GET" и Request.Form пусто. Однако, когда я перехожу к своему действию контроллера (AddEntry) и углубляюсь в запрос в обеих ситуациях, я вижу, что Request.HttpMethod и Request.Form имеют свои правильные значения.

Теперь вопрос в том, как исправить версию с Spring.NET, чтобы она работала так же, как та, которая использует Unity Framework?

Ответы [ 2 ]

4 голосов
/ 30 декабря 2008

Я нашел ответ!

Мое определение объекта выглядело так:

<!-- Controlers -->
<object name="Home" type="MyBlog.Controllers.HomeController">
    <property name="BlogService" ref="BlogService" />
    <property name="BlogEntryService" ref="BlogEntryService" />
    <property name="BlogEntryCommentService" ref="BlogEntryCommentService" />
</object>

Не берите в голову устанавливаемые свойства, что он фактически делает, это возвращает тот же самый экземпляр каждый раз, когда я запрашиваю этот объект, используя

IController result = context.GetObject(controllerName) as IController;

Итак, когда я изменил определение на

<!-- 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>

все начало работать просто отлично.

С наилучшими пожеланиями, Matthias.

2 голосов
/ 04 января 2009

просто дополнительное примечание для пояснения этого поведения: контроллеры обрабатываются средой ASP.NET MVC как прототипы, но Spring по умолчанию использует одиночный режим. Поэтому вам необходимо явно пометить ваш объект как не одноэлементный в конфигурации контейнера. Предстоящий модуль интеграции Spring MVC позаботится об этом, так что тогда вы не столкнетесь с этим.

НТН, Эрих

...