2011-12-14 3 views
3

В моем приложении MVC У меня есть мнение, что модель выглядит примерно так:ASP.net MVC - Отдельные ViewModel для действий POST

public class ComplexViewModel 
{ 
    public ComplexDetailsViewModel Details1 { get; set; } 
    public ComplexDetailsViewModel Details2 { get; set; } 
} 

public class ComplexDetailsViewModel 
{ 
    public int Id { get; set; } 
    public string DisplayValue1 { get; set; } 
    public string DisplayValue2 { get; set; } 
    // ... 
} 

Первоначально я делал следующее, на мой взгляд:

@Html.HiddenFor(model => model.Details1.Id) 
@Html.HiddenFor(model => model.Details2.Id) 

@Html.DisplayFor(model => model.Details1.DisplayValue1) 
... 

я ВЫВЕСИТЬ полную модель к контроллеру:

public ActionResult Post(ComplexViewModel model) 

Я на самом деле не нужно ничего от ComplexViewMod эш для значений Id, за исключением, поэтому я решил создать еще одну модель представления, используемый специально для разноски данных:

public class PostViewModel 
{ 
    public int Details1Id { get; set; } 
    public int Details2Id { get; set; } 
} 

public ActionResult Post(PostViewModel model) 

Проблема заключается в том, что теперь мой @HiddenFor(model => model.Details1.Id) не отображает моей модели POST, поэтому ничего на самом деле не получает вывешенным.

Есть ли способ иметь отдельную структуру для моей модели POST и моей модели GET, все еще используя вспомогательный помощник HiddenFor?

ответ

1

Просто напишите HTML-код для скрытых входов вручную, а не используя Html Helpers.

<input type="hidden" id="Details1Id" value="@Model.Details1.Id"/> 
<input type="hidden" id="Details2Id" value="@Model.Details1.Id"/> 

Update

Я имел проблемы делать что-то подобное. Я закончил сглаживать свойства, связанные с формой, на моих взглядах. Automapper позволяет легко сопоставлять другие объекты с вашим видом и выравнивать иерархии. Сделав это, ваше новое представление может выглядеть похоже на это.

public class ComplexViewModel   
{   
    public long Details1Id { get; set; }   
    public string Details1Name { get; set; } 
    public long Details2Id { get; set; }  
    public string Details2Name { get; set; }  
} 
+0

Я знал, что смогу это сделать, но я надеялся, что будет еще способ использовать помощников. Однако, похоже, это не так. – Dismissile

+0

Вы можете использовать @ Html.Hidden вместо @ Html.HiddenFor(), чтобы выполнить это, правильно? – hawkke

+1

Да, но я надеялся продолжать использовать HiddenFor, так как он автоматически добавляет префикс для вложенных шаблонов. – Dismissile

5

Просто потому, что вы не используете все данные в версии POST, это не значит, что вы должны создать другую модель. Почему бы не сохранить его простым?

Вот как это должно работать:

Ваш пост детали просмотра должен быть строго типизированными к конкретной модели представления. Затем в вашем контроллере вы имеете два результата действия с именем Post, например, один украшен атрибутом [HTTPGET], а действие, которое вы хотите отправить, украшено атрибутом [HTTPPOST]. Кроме того, ваш метод get должен принимать такой параметр, как post id, а ваш метод post должен принимать модель в качестве параметра.

Чтобы правильно применять проверки на стороне сервера, вы можете украсить свои свойства класса как так:

public class ComplexDetailsViewModel 
{ 
    [Required]//Works for just the Id property 
    public int Id { get; set; } 
    public string DisplayValue1 { get; set; } 
    public string DisplayValue2 { get; set; } 
    // ... 
} 

Теперь в вашем контроллере вы можете использовать это логическое значение: ModelState.IsValid. В принципе, если бы они отключили JavaScript и модель была отправлена ​​без Id, тогда модель была бы недействительной.

Этот шаблон очень мощный и позволяет быстро выполнять проверку на стороне клиента и на стороне сервера. И, конечно же, проверка на стороне клиента использует jQuery из коробки, поэтому мы можем легко расширить валидаторы. Вы даже можете сделать проверку AJAX очень быстро. Когда я строю свои формы, я не жертвую нигде, когда дело доходит до проверки. Так как для этого не требуется времени, чтобы сделать это правильно.

Чтобы ответить на исходный вопрос:

мнение может только быть сильно типизированных одной модели. Вы не можете загрузить представление с одной моделью и разместить ее другим (насколько я знаю). Я думаю, что если вы пытаетесь это сделать, ваша проблема в том, как вы построили свою модель.

+0

Мне нравится простота модели POST, потому что она упрощает работу с моими валидаторами. Вместо того, чтобы иметь сложные модели, у меня есть только два целых числа, с которыми я могу легко работать. – Dismissile

+0

@ Dismissile. Я обновлю свой ответ, чтобы дать вам пример того, как вы можете заставить валидаторы работать только с требуемым идентификатором. –

+0

У меня есть валидаторы, работающие с оригинальным способом, который я написал, и мне они не нравятся. Я переписал модель, чтобы сделать ее намного чище. Я доволен тем, как выглядит модель, я просто хотел узнать, можно ли использовать помощники, чтобы они могли «сопоставить» с другим свойством модели. – Dismissile

1

Модели должны быть более похожими. Одна ваша модель «Вид» обладает свойствами класса, а ваша модель «Почта» - нет. Если имена свойств класса и свойства не совпадают, они не привязаны привязкой модели. Попробуйте что-то вроде:

public class ComplexViewModel 
{ 
    public ComplexDetailsViewModel Details1 { get; set; } 
    public ComplexDetailsViewModel Details2 { get; set; } 
} 

public class ComplexDetailsViewModel : PostDetailsModel 
{ 
    public string DisplayValue1 { get; set; } 
    public string DisplayValue2 { get; set; } 
} 

public class PostModel 
{ 
    public PostDetailsModel Details1 { get; set; } 
    public PostDetailsModel Details2 { get; set; } 
} 

public class PostDetailsModel 
{ 
    public int Id { get; set; } 
} 

Большая проблема не используя те же модели между View и Post является проверка. Что произойдет, если вы хотите изменить валидацию (предполагая использование встроенной проверки MVC для клиентской и серверной сторон). Теперь вам нужно изменить обе модели! Ой, подождите ... Нет, ты не ...

public interface MyValidation 
{ 
    [required] 
    public int id { get; set; } 
} 

Затем просто добавить эти проверки в классы: (MetadataType рассказывает MVC, что использовать для проверки)

[MetadataType(typeof(MyValidation))] 
public class ComplexDetailsViewModel .... 

[MetadataType(typeof(MyValidation))] 
public class PostDetailsModel .... 

Это, конечно, будет работа, но я бы ВЫСОКО отговаривал, чтобы кто-нибудь использовал две разные модели между представлениями и обратной почтой. В этом случае я не вижу абсолютно никакой причины, почему они должны быть разными.

0

Просто: просто взгляните на модель вашего вида наследуйте от вашей модели пост-модели. Затем ваши методы HiddenFor работают, вам просто нужно убедиться, что свойства, которые вы ожидаете опубликовать, находятся в базовом классе (модель публикации).

Смежные вопросы