2010-02-11 4 views
4

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

В этом классе существует ряд свойств, которые непосредственно сопоставляются с классом 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) 

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

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

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

EDIT: Чтобы уточнить логическую схему:

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

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

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

+0

Ваш в создании, не так ли, чтобы иметь нулевое значение, если они не установлены? Что хотите, пустая строка? –

+0

Это не совсем то, что я имел в виду, я уточнил вопрос. –

+0

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

ответ

4

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

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

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

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

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

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

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

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

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

    Session["OpenIdClaimedIdentifier"] = value;

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

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

+0

Благодарим вас за обновленный ответ. Процесс двухступенчатого DB-фиксации не был тем, что я рассматривал. Я продолжу расследование и посмотрю, что я могу найти. –

+0

Dang edit timer: Я рад использовать скрытое поле, если это стандартный способ сделать это. Мне нравится идея двухэтапного процесса, но разве это не означает, что в какой-то момент мне нужно будет сохранить идентификатор пользователя модели в форме для обновления БД? Или это, где работает [Bind] Exclude? –

+0

@Alistair Обычно вы должны хранить идентификатор пользователя в cookie аутентификации. Таким образом, вы знаете, что идентификатор пользователя не был изменен. См. Мое обновление. –

1

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

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

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

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

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

1

Если вы хотите использовать 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 ...