Не редактируемые свойства ViewModel в представлении редактирования - PullRequest
4 голосов
/ 11 февраля 2010

В моем приложении ASP.NET MVC2 у меня есть класс ViewModel с именем UserCreateViewModel.

В этом классе есть ряд свойств, которые напрямую отображаются в класс LINQ-to-SQL, который называется User. Я использую AutoMapper для выполнения этого сопоставления, и он отлично работает.

В моем действии Создать UserController я получаю частично завершенную UserCreateViewModel, которая содержит информацию, касающуюся аутентификации OpenId.

это определение UserCreateViewModel:

public class UserCreateViewModel
{
    public string OpenIdClaimedIdentifier { get; set; }
    public string OpenIdFriendlyIdentifier { get; set; }
    public string Displayname { get; set; }
    public string Email { get; set; }
    public string PhoneNumber { get; set; }
}

В представлении «Создать» я не хочу, чтобы OpenIdClaimedIdentifier или OpenIdFriendlyIdentifier были доступны для редактирования.

Я использовал строго типизированное представление создания (используя встроенное автоматическое создание), но это предоставляет мне редактируемые текстовые поля для этих двух свойств. Если я полностью удаляю определенный HTML, когда форма создания возвращается (и возвращается непосредственно в UserCreateViewModel):

 [AcceptVerbs(HttpVerbs.Post)]
 public ActionResult Create(UserCreateViewModel viewModel, string ReturnUrl)

возвращаемая модель представления не содержит значений для OpenIdClaimedIdentifier и OpenIdFriendlyIdentifier.

Я исследовал использование атрибута [HiddenInput], но мне не удалось это сделать. Я также попытался использовать скрытый тег <input/> в форме, который работает, но это кажется немного неуклюжим.

Есть ли лучший способ сделать это? или используется скрытый <input> единственный способ?

РЕДАКТИРОВАТЬ: Для уточнения логического потока:

  1. Пользователь пытается войти под своим OpenId.
  2. DotNetOpenAuth выполняет аутентификацию и в случае успеха возвращает OpenIdClaimedIdentifier и OpenIdFriendlyIdentifier.
  3. Я проверяю базу данных, чтобы проверить, есть ли уже пользователь с таким идентификатором.
  4. Если пользователя еще нет, создайте временный UserCreateViewModel с обоими установленными полями OpenId. Это хранится в TempData.
  5. Перенаправить на UserController Создать действие и отобразить представление Создать с этим частично завершенным UserCreateViewModel объектом.
  6. Этот бит является проблемой Затем пользователь заполняет другие данные (DisplayName и т. Д.) И публикует полученный UserCreateViewModel.

Проблема в том, что между шагами 5 и 6 параметры OpenId теряются, если они не связаны. Я не хочу показывать пользователю OpenIdClaimedIdentifier или OpenIdFriendlyIdentifier во время создания формы, но если я удаляю данные, их привязка теряется в сообщении.

Надеюсь, это немного прояснит вопрос

Ответы [ 3 ]

4 голосов
/ 11 февраля 2010

Я не уверен, что это то, что вы ищете, но если вы не хотите, чтобы OpenIdClaimedIdentifier автоматически связывался, вы можете добавить его в список исключений BindAttribute

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude="OpenIdClaimedIdentifier")]UserCreateViewModel viewModel, string ReturnUrl) {
}

Обновлено после редактирования

Есть ли лучший способ сделать это?

Лучше - относительный термин. Конечно, есть альтернативные способы достижения того, чего вы хотите, но скрытые поля <input> часто используются в подобных ситуациях, и, как вы заявили, работают.

<%=Html.Hidden("OpenIdClaimedIdentifier") %

Есть ли какая-то особая причина, по которой вы не хотите использовать скрытое поле? Это поможет нам лучше ответить на ваш вопрос.

Это потому, что вы беспокоитесь о безопасности? Исходя из того, как вы описали свой логический поток, использование скрытого <input> сделает вас уязвимым для кого-то, кто изменяет аутентифицированные OpenIdClaimedIdentifier и OpenIdFriendlyIdentifier скрытые значения перед отправкой. Если это ваша проблема, то вы можете зашифровать данные, проанализированные обратно клиенту.

Альтернативные решения:

  • Хранить данные в сеансе сервера.

    Session["OpenIdClaimedIdentifier"] = value;

  • Или разделите ваш процесс на два этапа (состоящих из двух коммитов базы данных). Обновление На шаге 4, когда вы подтвердили аутентификацию OpenId, вы создаете запись пользователя в своей базе данных, получаете созданный уникальный идентификатор записи и сохраняете его в файле cookie аутентификации (так как пользователь аутентифицируется на этом этапе). Затем вы перенаправляете на «редактировать данные пользователя». Страница редактирования затем берет идентификатор пользователя из файла cookie аутентификации для поиска записи пользователя, а не из формы.

Если вы выполняете необходимые проверки безопасности перед сохранением данных, я не вижу ничего плохого в использовании скрытых полей.

1 голос
/ 19 февраля 2010

Если вы хотите использовать атрибут HiddenInput, и в то же время использовать атрибут проверки в вашем классе, вы можете изменить свой UserCreateViewModel следующим образом:

public class UserCreateViewModel
{
    [HiddenInput(DisplayValue=false)]
    public string OpenIdClaimedIdentifier { get; set; }
    [HiddenInput(DisplayValue=false)]
    public string OpenIdFriendlyIdentifier { get; set; }
    [Required]
    public string Displayname { get; set; }
    [Required]
    [DataType(DataType.EmailAddress)]
    public string Email { get; set; }
    [Required]
    [DataType(DataType.PhoneNumber)]
    public string PhoneNumber { get; set; }
}

Для отображения вашей модели с атрибутом в вашем представлении вы используете

<%= Html.EditorForModel() %>

или для одного поля:

<%= Html.EditorFor(m => m.OpenIdClaimedIdentifier)%>

Таким образом, ваша модель будет проверяться автоматически, и у вас будет скрытое поле для ваших OpenIdClaimedIdentifier и OpenIdFriendlyIdentifier. Чтобы убедиться, что их значение не изменилось, я бы использовал cookie ...

1 голос
/ 15 февраля 2010

Проблема в том, что у вас есть двухэтапный процесс: половина данных поступает от вызова DotNetOpenAuth, а другая половина - от пользователя. Поскольку вы хотите, чтобы сначала вызывался вызов DotNetOpenAuth, вам нужно найти способ сохранить эти данные до окончательного сохранения в вызове базы данных.

Это должно быть сделано на клиенте, поэтому обычный подход для достижения такого рода вещей с помощью скрытых полей ...

<%=Html.Hidden("OpenIdClaimedIdentifier") %>
<%=Html.Hidden("OpenIdFriendlyIdentifier") %>

Другими вариантами на стороне клиента являются файлы cookie или URL, и ни один из них не выглядит более подходящим, чем скрытые поля.

В качестве альтернативы можно реструктурировать ваш подход так, чтобы ваши вызовы open auth создавали учетную запись пользователя и сохраняли ее в базе данных с подробностями, полученными из вызова DotNetOpenAuth. Затем перенаправьте пользователя на страницу редактирования учетной записи, где он сможет обновить свои данные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...