Invalid edit mode viewmodel properties

In my ASP.NET MVC2 application, I have a ViewModel class called UserCreateViewModel.

There are a number of properties in this class that map directly to the LINQ to SQL class called User. I use AutoMapper to do this mapping, and it works great.

In my Create UserController action, I get a partially populated UserCreateViewModel that contains OpenId authentication information.

this is the definition of 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; } } 

In the Create view, I do not want OpenIdClaimedIdentifier or OpenIdFriendlyIdentifier to be editable.

I used a strongly typed creation view (using the built-in automatic creation), but this gives me an editable text file for these two properties. If I completely remove the specific html when the creation form returns (and returns directly to the UserCreateViewModel):

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

the returned viewModel does not contain values ​​for OpenIdClaimedIdentifier and OpenIdFriendlyIdentifier .

I explored the use of the [HiddenInput] attribute, but I did not seem to be able to do the job. I also tried using the hidden <input/> in the form, which works, but it seems a bit awkward.

Is there a better way to do this? or uses a hidden <input> only way?

EDIT: To clarify the logical flow:

  • A user is trying to log in using his OpenId.
  • DotNetOpenAuth authenticates and, if successful, returns OpenIdClaimedIdentifier and OpenIdFriendlyIdentifier .
  • I am doing a database check to see if there is already a user with this identifier.
  • If the user no longer exists, create a temporary UserCreateViewModel with the OpenId fields set. This is stored in TempData .
  • Redirect to UserController. Create an action and display the Create view using this partially completed UserCreateViewModel .
  • This bit is a problem. The user then completes the other data (DisplayName, etc.) and publishes the resulting UserCreateViewModel .

The problem is that between steps 5 and 6, the OpenId parameters are lost if they are not connected. I don’t want to show the user OpenIdClaimedIdentifier or OpenIdFriendlyIdentifier during the creation of the form, but if I delete the data, their binding will be lost in the message.

Hope this simplifies the question a bit.

+4
source share
3 answers

I'm not sure if this is what you are looking for, but if you don't want to automatically bind OpenIdClaimedIdentifier , then you can add it to the BindAttribute exception list

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

Updated after editing

Is there a better way to do this?

Better relative term. Of course, there are alternative ways to achieve what you want, but hidden <input> fields are often used in such situations, and, as you stated, work.

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

Is there any specific reason why you don't want to use a hidden field? This will help us better answer your question.

Is it because you are concerned about security? By the way you described your logical flow, using a hidden <input> will leave you vulnerable to someone who OpenIdClaimedIdentifier authenticated hidden values ​​of OpenIdClaimedIdentifier and OpenIdFriendlyIdentifier before submitting. If this is your problem, you can encrypt the data processed back to the client.

Alternative solutions:

  • Store data in a server session.

    Session["OpenIdClaimedIdentifier"] = value;

  • Or divide the process into two stages (consisting of 2 database records). Refresh . In step 4, when you confirm the OpenId authentication, you create a user record in your database, create a unique record identifier and save it in a cookie for authentication (since the user is authenticated at this point), then you are redirected to β€œedit user data” . The "edit" page then takes the user ID from the authentication cookie to search for the user record, and not from the form.

If you perform the necessary security checks before saving data, I see nothing wrong with using hidden fields.

+4
source

The problem is that you have a two-step process with half the data coming from the DotNetOpenAuth call, and the other half from the user. As you want the DotNetOpenAuth call to appear first, you need to find a way to store this data until it is finally stored in the database call.

This should be done on the client, so the usual approach to achieving this kind of thing with hidden fields ...

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

Other options on the client side are cookies or URLs and do not seem more suitable than hidden fields here.

Alternatively, you could rebuild your approach so that your open auth calls create a user account and store it in a database with the data obtained from the DotNetOpenAuth call. Then redirect the user to the "Edit Account" page, where they can update their data.

+1
source

If you want to use the HiddenInput attribute, and at the same time use the validation attribute for your class, you can change your UserCreateViewModel as follows:

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

To display your model using an attribute in your view, you use

 <%= Html.EditorForModel() %> 

or for one field:

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

Thus, your model will be automatically checked, and you will have a hidden field for your OpenIdClaimedIdentifier and OpenIdFriendlyIdentifier. To make sure their meaning has not changed, I would use a cookie ...

+1
source

Source: https://habr.com/ru/post/1300953/


All Articles