Remote validation in MVC3 : simple way to pass the form value from custom view model to controller via Remote Attribute

There are so many article on web about the remote validation in MVC3. But I didn’t find the right article to get the perfect solution for my project. I just spend a week  to solve it by my own idea and it works like a charm. You are thinking what’s the problem as remote validation is so easy in MVC3. That’s right, but if you need to do remote validation against more then one parameter as well any type of value from form then, this article will help you a lot to make you job done perfectly.

This article covered the following topics:

  • What I want to do?
  • What I did and save my hair loss?
  • Is there any alternates?

What I want to do?

What want to do?

As per above picture, I want to send the bo_account_id, bo_account_no and hidden value of FormType to controller to check that bo_account_no is exist or not. This doesBoExist method will work for both create and edit view. That’s way I use hidden value as ‘create’ at create view and ‘edit’ at edit view. In case of bo_account_id, at create view it will send null value and edit view it will send bo account no of which data want to edit.

What I did and save my hair loss?

BO Model

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace StockPortfolio.Models
{
    [MetadataType(typeof(BO_Validation))]
    [Bind(Include = "vBONo,vBrokerID,vInvestorID,nCommision")]
    public partial class BO
    {
        public string FormType { get; set; }

        public BO()
        {
        }
    }
    public class BO_Validation
    {
        [Key]
        [HiddenInput(DisplayValue = false)]
        public string vBOID { get; set; }

        [Required]
        [Display(Name = "BO Account NO")]
        [Remote("doesBoExist", "BO", AdditionalFields = "FormType,vBOID", HttpMethod = "POST", ErrorMessage = "BO account no already exists. Please enter a different BO account no.")]
        public string vBONo { get; set; }

        [Required]
        [Display(Name = "Broker Name")]
        public string vBrokerID { get; set; }

        [Required]
        [Display(Name = "Investor Name")]
        public string vInvestorID { get; set; }

        [Required]
        [Range(0.01,1)]
        [Display(Name = "Commision")]
        public decimal nCommision { get; set; }

    }

}

BOCreate Model

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace StockPortfolio.Models
{
    [Bind(Exclude = "SelectedStockExchange")]
    public class BOCreate
    {
        stock_sadequeEntities db = new stock_sadequeEntities();

        public BO bo { get; set; }
        public IEnumerable<SelectListItem> StockExchange { get; set; }
        public IEnumerable<SelectListItem> BrokerSelect { get; set; }
        public IEnumerable<SelectListItem> InvestorSelect { get; set; }

        [Required]
        [Display(Name = "Stock Exchange")]
        public string vStockExID { get; set; }

        public BOCreate()
        {
        }

        public BOCreate(BO boes)
        {
            this.bo = boes;

            var queryA = db.StockExchanges.Select(c => new SelectListItem
            {
                Value = c.vStockExchangeID,
                Text = c.vStockExchangeName,
            });
            StockExchange = queryA.AsEnumerable();

            var queryB = db.Brokers.Select(c => new SelectListItem
            {
                Value = c.vBrokerID,
                Text = c.vBrokerName,
            }).Where(u => u.Value == bo.vBrokerID);
            BrokerSelect = queryB.AsEnumerable();

            var queryC = db.Investors.Select(c => new SelectListItem
            {
                Value = c.vInvestorID,
                Text = c.vInvestorName,
            });
            InvestorSelect = queryC.AsEnumerable();

        }
    }
}

BOController (Due to some security issue of my project I didn’t post all the code of this controller, but below code is enough to understand the concept)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;
using StockPortfolio.Models;
using StockPortfolio.Models.BOFolder;
using System.Web.Script.Serialization;
using MvcPaging;

namespace StockPortfolio.Controllers
{
    public class BOController : Controller
    {
        IBORepository BORepository;

        [HttpPost]
        public JsonResult doesBoExist(FormCollection parm)
        {
            BO bo = BORepository.GetBOByName(parm["bo.vBONo"], parm["bo.FormType"], parm["bo.vBOID"]);
            return Json(bo == null);
        }
    }
}

Create view (Due to some security issue of my project I didn’t post all the code of this view, but below code is enough to understand the concept)

@model StockPortfolio.Models.BOCreate

@{
    ViewBag.Title = "Create New BO Account";
}

<div class="row">
    <div class = "span8 offset2">
        <h1>Create New BO Account</h1>
        <hr />

        @if (!Html.ViewData.ModelState.IsValid)
        {
        <div class="alert alert-error">
          <a class="close" data-dismiss="alert">×</a>
          Incomplete data found. Please correct the errors and try again.
        </div>
        }

        @using (Html.BeginForm("Create", "BO", FormMethod.Post, new { @class = "form-horizontal", id = "BOform" })) 
        {
            <fieldset>
                @Html.HiddenFor(model => model.bo.FormType)

                <div class="control-group">
                    <label class="control-label" for="focusedInput">@Html.LabelFor(model => model.bo.vBONo)</label> 
                    <div class="controls">
                        @Html.TextBoxFor(model => model.bo.vBONo)
                        <span class="help-inline">@Html.ValidationMessageFor(model => model.bo.vBONo)</span>
                    </div>
                </div>
                <div class="form-actions">
                    <input type="submit" class="btn btn-primary" value="Create" /> 
                </div>
            </fieldset>
        }
        <P>@Html.ActionLink("Back to List", "Index")</P>
    </div>
</div>

I post all the required code. Now I will point the important code from above.

  1. FormType is created at BO model. (See BO Model [Line – 14])
  2. Use a remote validation attribute with required data. It contains AddtionalFields as FormType and vBOID (see BO Model [Line – 28])
  3. create a custom model with the object of BO and three SelectListItem StockExchange, BrokerSelect and InvestorSelect. This model is used for view. (see BOCreate Model [Line – 15 to 18])
  4. create a doesBoExist method with FormCollection parameter and pickup the individual data from parameter as parm["bo.vBONo"], parm["bo.FormType"], parm["bo.vBOID"] and that’s the main trick. (see BOController [Line – 20])

and that’s all.

Is there any alternates?

If you know any alternatives, please let us know.

This article is selected by ASP.NET and marked as Article of the Day.

Comments

comments

Powered by Facebook Comments

Leave a Reply

Your email address will not be published. Required fields are marked *


+ two = 4

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="">