Remote validation preventing data editing

2

I am using remote validation to prevent repeated emails in the database, which works fine when I do some registration. The problem is that the remote does not accept the original registry value, and does not allow me to save the changes made to the other fields. I saw a possible solution saying to pass the ID in a hidden text box, but it also did not work.

My Edit Action.

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Editar(Usuarios usuario) 
    {

        ViewBag.CountryList = p.GetCountries();
        if (ModelState.IsValid)
        {
            db.Entry(usuario).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index", "Home");
        }
        return View(usuario);
    }

Method that checks Email.

public JsonResult validaEmail(string email)
        {
            return Json(!db.Usuarios.Any(u => u.Email == email), JsonRequestBehavior.AllowGet);
        }

[Required(ErrorMessage = "Campo Obrigatório")]
[Display(Name = "E-mail")]
[Remote("validaEmail", "Validar",AreaReference.UseRoot,ErrorMessage = "E-mail já existente. Por favor, utilize outro E-mail")]
[EmailAddress]
public string Email { get; set; }
    
asked by anonymous 06.01.2015 / 01:52

1 answer

5

You have to pass the id even if you will not be able to change the object. It will look something like this:

public JsonResult validaEmail(string email, int id)
{
    return Json(!db.Usuarios.Any(u => u.Email == email && i.Id != id), JsonRequestBehavior.AllowGet);
}

I think this resolves:

[Remote("validaEmail", "Validar", AdditionalFields = "Id", AreaReference.UseRoot,ErrorMessage = "E-mail já existente. Por favor, utilize outro E-mail")]

I did a test here and it worked like this (you can see the tutorial and download the project zipped in link

HomeController (will always return false for testing):

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult About()
    {
        ViewBag.Message = "Your application description page.";
        return View();
    }

    public ActionResult Contact()
    {
        ViewBag.Message = "Your contact page.";

        return View();
    }

    public ActionResult EmailDisponivel(int? Id, string email)
    {
        return Json(false, JsonRequestBehavior.AllowGet);
    }
}

Model :

public class Usuario
{
    public int? Id { get; set; }
    [Required(ErrorMessage="Campo obrigatório")]
    public string Nome { get; set; }
    [Required(ErrorMessage = "Campo obrigatório")]
    [EmailAddress(ErrorMessage="Email inválido")]
    [Remote("EmailDisponivel", "Home", AdditionalFields = "Id", ErrorMessage = "E-mail já existente. Por favor, utilize outro E-mail")]
    public string Email { get; set; }
}

View (the view code for having html will look all weird but that's about it:

@model ValidacaoRemota.Models.Usuario

@{
    ViewBag.Title = "Index";
}

Index

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
    <h4>Usuario</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    @Html.HiddenFor(model => model.Id)

    <div class="form-group">
        @Html.LabelFor(model => model.Nome, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Nome, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Nome, "", 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>

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Save" class="btn btn-default" />
        </div>
    </div>
</div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}
    
06.01.2015 / 02:00