-1

I want to use remote validation to check to see if a Username exists. I am using a Viewmodel to create users. While I can do this to get validation for creation or editing purposes, it will not work for both creating and editing. Here is my model:

    [Required]
    [Display(Name = "Homeowner Username")]
    [Remote("doesUserNameExist", "Homeowners", HttpMethod = "POST", ErrorMessage = "User name already exists. Please enter a different user name.", AdditionalFields = "InitialUsername")]

Here is my edit view:

    @Html.Hidden("Homeowner.InitialUsername", Model.Username)


    <div class="form-group">
        @Html.LabelFor(model => model.Username, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Username, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Username, "", new { @class = "text-danger" })
        </div>
    </div>

Here is my controller in the version that works for registration but not editing(when editing, parameters are null):

    public JsonResult doesUserNameExist([Bind(Prefix = "Homeowner.Username")]string Username, [Bind(Prefix = "InitialUsername")] string InitialUsername)  
    {
       MY CODE
    }

Here is my controller that works for editing but not creating(when creating, both parameters are null):

    public JsonResult doesUserNameExist([Bind(Include = "Homeowner.Username")]string Username, [Bind(Include = "InitialUsername")] string InitialUsername)  
    {
       MY CODE
    }

I have tried many variations of this but just can't get it.

I have looked here: ASP.NET MVC Binding with Remote Validation

Here:

Remote ViewModel validation of nested objects not working

And here: http://forums.asp.net/t/1652512.aspx?Compound+View+Model+object+causing+remote+validation+failure

But I seem to be missing something. Is there a way I can make this work for both editing and registering? I am pretty new at this, and would greatly appreciate any ideas!

Edit:

Perhaps this is a poor design choice(first time using view models, only been coding a few months), but I was trying to create a new homeowner and address at the same time as when I create a new application user in that role. Here is the viewmodel I am using:

public class RegisterHomeownerViewModel
{
    [Required]
    [EmailAddress]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
    public int roles { get; set; }
    public virtual Address Address { get; set; }
    public virtual Homeowner Homeowner { get; set; }
}

Here is my method in the account controller:

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> RegisterHomeowner(RegisterHomeownerViewModel model, Address address, Homeowner homeowner)
    {
        ApplicationDbContext db = new ApplicationDbContext();

        if (ModelState.IsValid)
        {
            var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
            var result = await UserManager.CreateAsync(user, model.Password);
            if (result.Succeeded)
            {

                var role = db.Roles.Find("0");
                UserManager.AddToRole(user.Id, role.Name);
                await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
                db.Addresses.Add(address);
                homeowner.UserId = user.Id;
                homeowner.AddressID = address.ID;
                db.Homeowners.Add(homeowner);
                db.SaveChanges();


                return RedirectToAction("Index", "Homeowners");

            }
            AddErrors(result);
        }

        return View(model);
    }

Here is the view I am using to create those entities:

<div class="form-horizontal">
    <h4>RegisterViewModel</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    <div class="form-group">
        @Html.LabelFor(model => model.Homeowner.Username, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Homeowner.Username, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Homeowner.Username, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
        </div>
    </div>

Everything does work as far as I can tell except for remote validation on Username. I can get it to give me an error when creating in the account method above, or I can get an error when editing by deleting the Prefix (which makes it so my Username is not recognized. There is obviously something I am doing wrong.

Community
  • 1
  • 1
Pennywise
  • 281
  • 2
  • 4
  • 11
  • Show the view for the create method. And if your using a view model, why in the world do you have `Homeowner.InitialUsername` instead of simply `InitialUsername`. And having a `Bind(Include="..")` makes no sense (you not posting a model). And how can there be an `InitialUsername` when creating? –  Aug 28 '16 at 06:44
  • I edited my post with some more details. I am able to pull InitalUsername by changing it just as you suggested, but still can't get both Username and InitalUser name at the same time when trying to edit. Thanks for the tips in the post above. Before I was not able to pull InitialUsername at all. – Pennywise Aug 28 '16 at 09:15
  • A [view model](http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc) should not contain data models, and certainly not virtual properties. But what are you trying to do with your `Remote` attributes (what you have shown so far makes no sense). And in any case, you need 2 separate models for create and edit) –  Aug 28 '16 at 09:32
  • Thanks for the tips. I do appreciate it. – Pennywise Aug 28 '16 at 09:36
  • Got it. Thanks so much Stephen! Your blunt guidance really helped a lot. – Pennywise Aug 28 '16 at 22:09

1 Answers1

0

I got it. I read Stephen's post a few times and a few threads on virtual properties. I went to bed, got up, and revised my viewmodel by removing all data models. Then, for validation when creating, I compared the input to the validation properties in my view model instead of my actual model. This works for creation. Then when I edit, I compare my input against the validation properties in my actual model. It made sense when I learned you can have different validation for a viewmodel than there is in the model. This thread helped too: View Model virtual properties and drop down lists. Thanks so much! I learned a lot from this!

Community
  • 1
  • 1
Pennywise
  • 281
  • 2
  • 4
  • 11