Posting a null validation from drop down list MVC - c#

I am working to develop an application asp.net MVC that has a text box and two drop down lists. Users can input a numeric value and choose from the list from - to to process . My problem is trying to validate the drop down list as I tried to use the required validation but didn't work. I also tried to check on the drop downs when sending null values but the error validation doesn't work!
The error type:
There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'fromCurrency.Name'.
Contorller
[HttpPost]
public ActionResult Index(Currencies cur)
{
if (ModelState.IsValid)
{
if (String.IsNullOrWhiteSpace(cur.fromCurrency.Name) || String.IsNullOrWhiteSpace(cur.toCurrency.Name))
{
ModelState.AddModelError(string.Empty, "you can not leave the empty dropdown please select any of these");
}
else
{
var fromCurrencyList = CurrenciesClient.GetFromCurrencyListAsync().Result;
ViewBag.FromCurrencies = new SelectList(fromCurrencyList, "CurrencyCode", "Name");
var ToCurrencyList = CurrenciesClient.GetToCurrencyListAsync().Result;
ViewBag.ToCurrencies = new SelectList(ToCurrencyList, "CurrencyCode", "Name");
var fromcurrname = cur.fromCurrency.Name;
string tocurrname = cur.toCurrency.Name;
//rate is taking by passing both dropdown currency code
decimal rate = CurrenciesClient.GetConversionRate("Currencies/GetConversionRate?fromcurrname=" + fromcurrname + "&tocurrname=" + tocurrname).Result;
ViewBag.TheResult = cur.CurrencyToConvert * rate;
}
}
return View();
}
Index View
#model ViewModel.Currencies
#{
ViewBag.Title = "Index";
}
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<div id="ConversionSection">
<form class="form-horizontal" method="post" id= "CurrencyConversion" action="/Currency/Index">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<label class="col-sm-4 control-label">
#Html.LabelFor(m => m.CurrencyToConvert, "Enter Currency")
</label>
<div class="col-sm-4">
#Html.EditorFor(m => m.CurrencyToConvert, new { #class = " form-control" })
#*#Html.ValidationMessageFor(m => m.CurrencyToConvert)*#
#Html.ValidationMessageFor(m => m.CurrencyToConvert, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">
#Html.LabelFor(model => model.fromCurrency.Name, "From Currency")
</label>
<div class="col-sm-4">
#Html.DropDownListFor(m => m.fromCurrency.Name, ViewBag.FromCurrencies as SelectList, "--select--", new { #class = " form-control" })
#Html.ValidationMessageFor(model => model.fromCurrency.Name)
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">
#Html.LabelFor(model => model.toCurrency.Name, "To Currency")
</label>
<div class="col-sm-4">
#Html.DropDownListFor(m => m.toCurrency.Name, ViewBag.ToCurrencies as SelectList, "--select--", new { #class = "form-control" })
#*#Html.ValidationMessageFor(model => model.toCurrency.Name)*#
#Html.ValidationSummary(false, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">
#Html.LabelFor(l => l.ConvertedCurrency, "Value")
</label>
<div class="col-sm-4">
#Html.Editor("TheResult", new { #class = " form-control" })
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-4">
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
</form>
</div>
Currencies.cs
public class Currencies
{
[Required]
[DataType(DataType.Currency)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public decimal CurrencyToConvert { get; set; }
public Currency fromCurrency { get; set; }
public Currency toCurrency { get; set; }
public double ConvertedCurrency { get; set; }
}

Since nothing is return if your modelstate will be invalid. So viewbag.FromCurrencies and Viewbag.ToCurrencies should be outside of if (ModelState.IsValid).If you will not add Viewbag properties code after if(ModelState.IsValid) null value will be passed through it and you will get this exception. I am writing here refactored code in httppost method.
[HttpPost]
public ActionResult Index(ConvertCurrencyViewModel cur)
{
if (ModelState.IsValid)
{
string fromcurrname = cur.fromCurrency.Name;
string tocurrname = cur.toCurrency.Name;
//rate is taking by passing both dropdown currency code
decimal rate = CurrencyClient.GetConversionRate("Currency/GetConversionRate?fromcurrname=" + fromcurrname + "&tocurrname=" + tocurrname).Result;
ViewBag.result = cur.CurrencyToConvert * rate;
}
//getting this select list value form Currency client class
var fromCurrencyList = CurrencyClient.GetFromCurrencyListAsync().Result;
ViewBag.FromCurrencies = new SelectList(fromCurrencyList, "CurrencyCode", "Name");
var ToCurrencyList = CurrencyClient.GetToCurrencyListAsync().Result;
ViewBag.ToCurrencies = new SelectList(ToCurrencyList, "CurrencyCode", "Name");
return View();
}
And modifiy your curreny class like this to show validation error.
public class Currencies
{
[Required(AllowEmptyStrings = false, ErrorMessage = "Please enter amount to convert")]
[DataType(DataType.Currency)]
[DisplayFormat(ConvertEmptyStringToNull = false)]
public decimal CurrencyToConvert { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "Please select country Name")]
public Currency fromCurrency { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "Please select country Name")]
public Currency toCurrency { get; set; }
public double ConvertedCurrency { get; set; }
}
This will help you to validate your fields.

Related

Values lost when sent to controller

I want to send my EmailFormModel, which contains the Ressurs-list, to the controller where i want to do stuff with it. However I'm never able to access the values in my EmailFormModel in my controller. I tried to overcome this problem by using Sessions, but still it doesnt work.
The list Ressurs contains several Ressursbehov, but there is never more than one EmailFormModel.
My controller
namespace WebApplication6.Controllers
{
public class AppController : Controller
{
const string SESSION_SAVED_MODEL = "savedModel";
[HttpGet]
public ActionResult Index()
{
Session[SESSION_SAVED_MODEL] = new EmailFormModel();
return View(Session[SESSION_SAVED_MODEL]);
}
public ActionResult Sent()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Index(EmailFormModel model)
{
//other irrelevant code
if (Request.Params["Ekstra_Ressurs"] != null)
{
model.Ressurs.Add(new RessursBehov());
Session[SESSION_SAVED_MODEL] = model;
}
}
return View(model);
}
}
My model
namespace WebApplication6.Models
{
public class EmailFormModel
{
[Required, Display(Name = "Prosjektnummer")]
public string Prosjektnummer { get; set; }
[Required, Display(Name = "Prosjektnavn")]
public string Prosjektnavn { get; set; }
[Required, Display(Name = "Prosjekttype")]
public string Prosjekttype { get; set; }
[Required, Display(Name = "Prosjektleder")]
public string Prosjektleder { get; set; }
public List<RessursBehov> Ressurs = new List<RessursBehov>()
{
new RessursBehov() };
}
public class RessursBehov
{
[Required, Display(Name = "Ressurstype")]
public string Ressurstype { get; set; }
[Required, Display(Name = "Navn på ressurs")]
public string Navn_På_Ressurs { get; set; }
[Required, Display(Name = "Ukenummer")]
public int? Ukenummer { get; set; }
[Required, Display(Name = "Antall timer")]
public int? Antall_Timer { get; set; }
[Required, Display(Name = "Antall uker")]
public int? Antall_Uker { get; set; }
}
}
}
My View
#model WebApplication6.Models.EmailFormModel
#{
ViewBag.Title = "Registrer nytt prosjekt";
List<SelectListItem> prosjektTypeListe = new List<SelectListItem>()
{
new SelectListItem { Text = "Prosjekt", Value = "Prosjekt" },
new SelectListItem { Text = "Forvaltning", Value = "Forvaltning" }
};
List<SelectListItem> ressurstypeliste = new List<SelectListItem>()
{
new SelectListItem { Text = "utvikler", Value = "utvikler" },
new SelectListItem { Text = "frontendutvikler", Value = "frontendutvikler" },
new SelectListItem { Text = "epi-utvikler", Value = "epi-utvikler" },
new SelectListItem { Text = "webnodesutvikler", Value = "webnodesutvikler" },
new SelectListItem { Text = "designer", Value = "designer" },
new SelectListItem { Text = "rådgiver", Value = "rådgiver" },
new SelectListItem { Text = "prosjektleder", Value = "prosjektleder" }
};
}
<div class="title">
<div class="text-center">
<h2>#ViewBag.Title</h2>
</div>
</div>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="rows">
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => m.Prosjektnummer, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.TextBoxFor(m => m.Prosjektnummer, new { #class = "html_label" })
#Html.ValidationMessageFor(m => m.Prosjektnummer)
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => m.Prosjektnavn, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.TextBoxFor(m => m.Prosjektnavn, new { #class = "html_label" })
#Html.ValidationMessageFor(m => m.Prosjektnavn)
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => m.Prosjekttype, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.DropDownListFor(m => m.Prosjekttype, prosjektTypeListe, "-- Velg Prosjekttype --", new { #class = "dropdown" })
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => m.Prosjektleder, new { #class = "col-md-1 text-center" }) <!--tar inn m som parameter og returnerer m.prosjektleder-->
<div class="col-md-7">
#Html.TextBoxFor(m => m.Prosjektleder, new { #class = "html_label" })
#Html.ValidationMessageFor(m => m.Prosjektleder)
</div>
</div>
#for (var i = 0; i < Model.Ressurs.Count; i++)
{
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => Model.Ressurs[i].Ressurstype, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.DropDownListFor(m => Model.Ressurs[i].Ressurstype, ressurstypeliste, "-- Velg ressurstype --", new { #class = "dropdown" })
</div>
</div>
<div class="row">
<div class="col-md-3"></div>
#Html.LabelFor(m => Model.Ressurs[i].Navn_På_Ressurs, new { #class = "col-md-2 text-right" })
<div class="col-md-7">
#Html.TextBoxFor(m => Model.Ressurs[i].Navn_På_Ressurs, new { #class = "html_label" })
#Html.ValidationMessageFor(m => Model.Ressurs[i].Navn_På_Ressurs)
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => Model.Ressurs[i].Ukenummer, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.TextBoxFor(m => Model.Ressurs[i].Ukenummer, new { #class = "html_label" })
#Html.ValidationMessageFor(m => Model.Ressurs[i].Ukenummer)
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => Model.Ressurs[i].Antall_Timer, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.TextBoxFor(m => Model.Ressurs[i].Antall_Timer, new { #class = "html_label" })
#Html.ValidationMessageFor(m => Model.Ressurs[i].Antall_Timer)
</div>
</div>
<div class="row">
<div class="col-md-4"></div>
#Html.LabelFor(m => Model.Ressurs[i].Antall_Uker, new { #class = "col-md-1 text-center" })
<div class="col-md-7">
#Html.TextBoxFor(m => Model.Ressurs[i].Antall_Uker, new { #class = "html_label" })
#Html.ValidationMessageFor(m => Model.Ressurs[i].Antall_Uker)
</div>
</div>
}
<br />
<div class="row">
<div class="col-md-5"></div>
<div class="col-md-2">
<input type="submit" class="btn btn-default" value="Legg til ressurser" name="Ekstra_Ressurs" />
</div>
<div class="col-md-2">
<input type="submit" class="btn btn-primary" value="Send inn mail" name="Sendknapp" />
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
In order to reach model in HttpPost Index action
1) You should pass EmailFormModel type model to View in the GET Index action method.
EmailFormModel model = new EmailFormModel();
Session[SESSION_SAVED_MODEL]=model;
return View(model);
2) You should use Model at the lambda expressions
#Html.TextBoxFor(m => Model.Prosjektleder, new { #class = "html_label" })
change all ms with Model.
All you have to do is add #Name in html attribute then you wont need to use session also .
#Html.DropDownListFor(m => m.Prosjekttype, prosjektTypeListe , "-- Velg Prosjekttype --", new { #class = "dropdown" , #Name = "Prosjekttype" })

ASP.NET MVC-5 sever side validation not working

I have ASP.NET MVC application and I am failing to Server-side and client-side validation for partial page. In the start of my application there is login page which validating correctly. so if I press submit with no values in form, app don't show any error messages
model class
public class CreateFunctionNavigation_SP_Map
{
public CreateFunctionNavigation_SP_Map()
{
}
//Function Table
[StringLength(250)]
[Required(ErrorMessage = "Required Function Title")]
[Display(Name = "Function Title")]
public string FunctionName { get; set; }
[Required(ErrorMessage = "Required Function Hierarchy; i.e Where Function Exists In Hierarchy Tree \n Top-Level Start From 1 ")]
[Display(Name = "Function Hierarchy Level")]
public int FunctionHierarchy_Level { get; set; }
//Controller Table
[StringLength(250)]
[Required(ErrorMessage = "Required Controller Title")]
[Display(Name = "Controller Title")]
public string ControllerName { get; set; }
//Action Table
[StringLength(250)]
[Required(ErrorMessage = "Required Action Title")]
[Display(Name = "Action Title")]
public string ActionName { get; set; }
// Hierarchy Table
[Required(ErrorMessage = "Required Function Parent - Child Relation ID \n Put 0 In Case Given Function doesn't Have Any Parent Function ")]
[Display(Name = "Function Parent's FunctionID")]
public int Function_ParentsFunctionID { get; set; }
}
controller method
#region CreateNewFunctionNavigation
[HttpGet]
public ActionResult CreateNewFunctionNavigation()
{
return PartialView("CreateNewNavigation_Partial");
}
#endregion
[HttpPost]
public ActionResult CreateNewFunctionNavigation(CreateFunctionNavigation_SP_Map obj )
{
try
{
if(ModelState.IsValid)
{
_FN_Services_a2.CreateFunctionNavigation(obj);
}
}
catch (DataException ex)
{
ModelState.AddModelError("", "Unable To Create New Function Navigation" + ex);
}
return RedirectToAction("SystemCoreHome");
} //end
view
#model App.DAL.Model.CreateFunctionNavigation_SP_Map
<div class="_Form_Block">
#using (Html.BeginForm("CreateNewFunctionNavigation", "SystemCore", FormMethod.Post, new { id = "NewFunctionNavigationForm" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(#model => #model.FunctionName, new { #class = "control-label col-md-2" })
<div class="form-group">
#Html.EditorFor(#model => #model.FunctionName)
#Html.ValidationMessageFor(#model => #model.FunctionName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(#model => #model.FunctionHierarchy_Level, new { #class = "control-label col-md-2" })
<div class="form-group">
#Html.EditorFor(#model => #model.FunctionHierarchy_Level)
#Html.ValidationMessageFor(#model => #model.FunctionHierarchy_Level)
</div>
</div>
<div class="form-group">
#Html.LabelFor(#model => #model.ControllerName, new { #class = "control-label col-md-2" })
<div class="form-group">
#Html.EditorFor(#model => #model.ControllerName)
#Html.ValidationMessageFor(#model => #model.ControllerName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(#model => #model.ActionName, new { #class = "control-label col-md-2" })
<div class="form-group">
#Html.EditorFor(#model => #model.ActionName)
#Html.ValidationMessageFor(#model => #model.ActionName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(#model => #model.Function_ParentsFunctionID, new { #class = "control-label col-md-2" })
<div class="form-group">
#Html.EditorFor(#model => #model.Function_ParentsFunctionID)
#Html.ValidationMessageFor(#model => #model.Function_ParentsFunctionID)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default _formButton" />
<input type="button" value="Cancel" class="btn btn-default _formButton" onclick="CancelPage();" />
</div>
</div>
}
</div> <!--End _Form_Block-->
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
instead of
return RedirectToAction("SystemCoreHome");
use
return PartialView("CreateNewNavigation_Partial", obj);
Ajax Form
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "TargetID" }))
{
...
}
<div class="_Form_Block" id="TargetID">
</div>
You need to handle this case.
Presently you are not doing anything in the event that the ModelState is invalid. Try the following:
public ActionResult CreateNewFunctionNavigation(CreateFunctionNavigation_SP_Map obj)
{
if (!ModelState.IsValid)
{
return View(obj);
}
// rest of method here
if(ModelState.IsValid)
{
_FN_Services_a2.CreateFunctionNavigation(obj);
}
else
{
return View();
}
Should do the trick.

How can I retrieve selected item's both Text and Value from DropDownList in MVC

Model:
public class SelectBillingSiteReportModel
{
public IEnumerable<SelectListItem> Sites { get; set; }
public string SelectedSiteName { get; set; }
public string SelectedSiteKey { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime FromDateTime { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime ToDateTime { get; set; }
}
View:
#model MuseReport.Models.SelectBillingSiteReportModel
#{
ViewBag.Title = "Select Site and Date Range";
}
<div class="page-header">
<h4>Select Site and Date Range for Ecg Billing Summary</h4>
</div>
<div class="row">
#using (Html.BeginForm("EcgBilling", "BillingRpt"))
{
<div class ="form-horizontal" role="form">
<div class="form-group">
#Html.Label( "Muse Site", new { #class = "col-md-2 control-label"})
<div class="col-md-10">#Html.DropDownListFor(model => model.SelectedSiteKey, Model.Sites, new { id="museSites", #class = "selectpicker"})</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FromDateTime, "From Date", new { #class = "col-md-2 control-label"})
<div class="col-md-10">#Html.EditorFor(model => model.FromDateTime)</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ToDateTime, "To Date", new { #class = "col-md-2 control-label"})
<div class="col-md-10">#Html.EditorFor(model => model.ToDateTime)</div>
</div>
<div class="form-group">
<div class="col-md-10">#Html.HiddenFor(model => model.SelectedSiteName)</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="submit" class="btn btn-primary">Go</button>
</div>
</div>
</div>
}
In a perfect world, I would like to get the whole SelectListItem that the user has selected in the dropdown, rather than just the Value in model.SelectedSiteKey. At worst, I would like to get the Text associated with the Value that was selected into the hidden field (model.SelectedSiteName).
My research suggests that I could use javascript, or I could use an EditorTemplate, neither of which I am clear on how to do.
It seems like this is a lot of work just to trap one extra text string. Am I missing an obvious way to get the text value from the dropdown on the selection?
I just want to save the text value for display with my results without
having to do another call back to the first db.
Based on your comment, you can combine both Text and Value store inside Value. Then split it when the Form is posted back.
For example -
public ActionResult EcgBilling()
{
var model = new SelectBillingSiteReportModel
{
Sites = new List<SelectListItem>
{
new SelectListItem {Text = "One", Value = "One:1"},
new SelectListItem {Text = "Two", Value = "Two:2"},
new SelectListItem {Text = "Three", Value = "Three:3"},
}
};
return View(model);
}
[HttpPost]
public ActionResult EcgBilling(SelectBillingSiteReportModel model)
{
string[] array = model.SelectedSiteKey.Split(':');
string text = array[0];
string value = array[1];
return View();
}
create two fields, 1-value, 2-text,
in the html page
get the selected item's text and assign it to text field
<input id="text_field" name="text_field" type="hidden" />
#Html.DropDownList("value_field", null, " ---Select ---", new { #id = "value", #class = "form-control selectpicker", required = "required", style = "width:180px" })
//jquery
$('#value').change(function () {
var text = $("option:selected", this).text();
$('#text_field').val(text);
});
this way you can save both text and value

Ajax.BeginForm with Dropdown + Server Side Validation

I am trying to build an Ajax.BeginForm (that has a dropdown) which uses server side validation that checks the model's annotations. I am having trouble getting the dropdown to work properly. Originally I populated the dropdown using the viewbag as such:
view:
#Html.DropDownList("CheckIn_Location", ViewBag.CageLocationList as IEnumerable<SelectListItem>, "(Select one)", new { #class = "form-control" })
controller:
public void GetCageLocations()
{
IEnumerable<SelectListItem> selectList =
from c in db.Locations
select new SelectListItem
{
Text = c.LocationName,
Value = c.Id.ToString()
};
ViewBag.CageLocationList = selectList;
}
But that didn't seem to play friendly with server side validation so I am tried reworking my model/view/controllers as such:
Here is my Model:
public class CheckInViewModel
{
public int CheckIn_Id { get; set; }
[Required(ErrorMessage = "Location Required.")]
public IEnumerable<SelectListItem> CheckIn_Location { get; set; }
[Required(ErrorMessage = "Quantity Required.")]
[Range(1, 100, ErrorMessage = "Quantity must be between 1 and 100000")]
public int CheckIn_Quantity { get; set; }
public string CheckIn_Comment { get; set; }
}
Here is my Controller:
[HttpPost]
public ActionResult CheckIn(CheckInViewModel model)
{
if (ModelState.IsValid)
{
var New_Transaction = new Transaction
{
Id = model.CheckIn_Id,
Quantity = model.CheckIn_Quantity,
LocationId = Convert.ToInt32(model.CheckIn_Location),
TransactionDate = DateTime.Now,
TransactionComments = model.CheckIn_Comment.Replace("\r\n", " ")
};
unitOfWork.TransactionRepository.Insert(New_Transaction);
unitOfWork.Save();
return PartialView("CheckIn", model);
}
return PartialView("CheckIn", model);
}
Here is my PartialView called CheckIn.cshtml
#model ViewModels.CheckInViewModel
<!-- Modal -->
<div class="modal fade" id="CheckInModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h1 class="modal-title" id="CheckInModalLabel">Check In</h1>
</div>
<div class="modal-body">
#using (Ajax.BeginForm("CheckIn", "Cage", null, new AjaxOptions { HttpMethod = "POST", OnSuccess = "success", OnFailure = "failure"}, new { #id = "CheckInForm", #class = "form-horizontal" }))
{
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.CheckIn_Id, new { #class = "form-control" })
<div class="form-group">
<label for="CheckIn_Location" class="col-sm-4 control-label">Location</label>
<div class="col-sm-8">
#Html.DropDownListFor(x => x.CheckIn_Location, Model.CheckIn_Location, "Select One")
#Html.ValidationMessageFor(model => model.CheckIn_Location)
</div>
</div>
<div class="form-group">
<label for="CheckIn_Quantity" class="col-sm-4 control-label">Quantity</label>
<div class="col-sm-8">
#Html.TextBoxFor(model => model.CheckIn_Quantity, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.CheckIn_Quantity)
</div>
</div>
<div class="form-group">
<label for="CheckIn_Comment" class="col-sm-4 control-label">Comment</label>
<div class="col-sm-8">
#Html.TextAreaFor(model => model.CheckIn_Comment, new { #class = "form-control" })
</div>
</div>
}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" onclick="SubmitCheckInForm()">Check In</button>
</div>
</div>
</div>
</div>
here is the JS function that fire the submit:
function SubmitCheckInForm() {
$('#CheckInForm').submit();
}
Can someone show me how to:
populate the dropdown with (value/text) using the model as the binding agent (not the viewbag as I previously did it)
return the selected option to the controller and insert it into the transaction table's location element (which is an int)
properly hook this all up so the server side annotations work and return messages when something is incorrect in the form.
Thanks in Advance!
If I have understood you correctly, there is more than one way to do this. For instance, you could have two properties in your model to manage the Dropdown control.
1- CheckIn_Location_Selected. To store the value selected by the user
2- CheckIn_Location_List. To fill the DropdownList.
This could be your model.
public class CheckInViewModel
{
[Required(ErrorMessage = "Location Required.")]
public int CheckIn_Location_Selected { get; set; }
public IEnumerable<SelectListItem> CheckIn_Location_List { get; set; }
//Rest of the properties...
}
So now in your GET action you could have something like this:
[HttpGet]
public ActionResult CheckIn()
{
var model = new CheckInViewModel
{
CheckIn_Location_List = repository.GetCageLocations().Select(
location => new SelectListItem
{
Value = location.Id.ToString(),
Text = location.LocationName
})
};
return View(model);
}
And in your view:
#Html.DropDownListFor(x => x.CheckIn_Location_Selected, Model.CheckIn_Location_List, "Select One")
We need to change a bit your POST action.
[HttpPost]
public ActionResult CheckIn(CheckInViewModel model)
{
if (!ModelState.IsValid)
{
// This is necessary because we are sending the model back to the view.
// You could cache this info and do not take it from the DB again.
model.CheckIn_Location_List = repository.GetCageLocations().Select(
location => new SelectListItem
{
Value = location.Id.ToString(),
Text = location.LocationName
});
return PartialView("CheckIn", model);
}
var New_Transaction = new Transaction
{
Id = model.CheckIn_Id,
Quantity = model.CheckIn_Quantity,
LocationId = Convert.ToInt32(model.CheckIn_Location_Selected),
TransactionDate = DateTime.Now,
TransactionComments = model.CheckIn_Comment.Replace("\r\n", " ")
};
unitOfWork.TransactionRepository.Insert(New_Transaction);
unitOfWork.Save();
return PartialView("CheckIn", model);
}

dependency validation based on dropdown selecion in MVC4

I have a dropdropdown list have values Yes, No. If you select yes I have validate next two textboxes. How can I do dependency validation based on dropdown selection?
public class MeetingAbstract
{
public string HasMaterialPublishedElseWhereLabel { get; set; }
public string HasMaterialPublishedElseWhereOptions { get; set; }
[Required]
public string HasMaterialPublishedElseWhereText { get; set; }
public string DtPublishedTimeId { get; set; }
public string DtPublishedTimeLabel { get; set; }
//validate this based on HasMaterialPublishedElseWhereText =Yes value
public string DtPublishedTimeText { get; set; }
public string PublishedPlaceId { get; set; }
public string PublishedPlaceLabel { get; set; }
//validate this based on HasMaterialPublishedElseWhereText =Yes value
public string PublishedPlaceText { get; set; }
}
view
<div class="row" style="padding-bottom: 10px">
<div class="col-md-10">
<div class="col-md-6">#Html.Label(Model.HasMaterialPublishedElseWhereLabel,
new {#class = "control-label mandatory"})</div>
<div class="col-md-4">
#{
options = Model.HasMaterialPublishedElseWhereOptions;
optionsList = options.Split(',').ToList();
optionSelect = optionsList.Select(option => new SelectListItem()
{Text = option, Value = option}).ToList();
}
#Html.DropDownListFor(model => model.HasMaterialPublishedElseWhereText,
optionSelect, i18n_Models_Abstract.SelectOption, new { #class = "input-
validation-error form-control" })
#Html.ValidationMessageFor(model => model.HasMaterialPublishedElseWhereText,
i18n_Models_Abstract.RequiredField,
new { style = "padding-left: 5px" })
</div>
</div>
</div>
<div class="row" style="padding-bottom: 10px">
<div class="col-md-10">
<div class="col-md-6">#Html.Label(Model.DtPublishedTimeLabel, new {#class =
"control-label mandatory"})</div>
<div class="col-md-4">#Html.TextBoxFor(model => model.DtPublishedTimeText, new \
{#class = "form-control", #placeholder = Model.DtPublishedTimeLabel,
required = "required", maxlength = 40})
#Html.ValidationMessageFor(model => model.DtPublishedTimeText,
i18n_Models_Abstract.RequiredField, new { style = "padding-left: 5px" })</div>
</div>
</div>
<div class="row" style="padding-bottom: 10px">
<div class="col-md-10">
<div class="col-md-6">#Html.Label(Model.PublishedPlaceLabel, new {#class =
"control-label mandatory"})</div>
<div class="col-md-4">#Html.TextBoxFor(model => model.PublishedPlaceText, new
{#class = "form-control", #placeholder = Model.PublishedPlaceLabel,
required = "required", maxlength = 40})
#Html.ValidationMessageFor(model => model.PublishedPlaceText,
i18n_Models_Abstract.RequiredField, new { style = "padding-left: 5px" })
</div>
</div>
</div>
I would add a Validate method on your model which will be called and exposed via ModelState.IsValid:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (this.HasMaterialPublishedElseWhereText == "Yes") {
yield return new ValidationResult("This isn't valid! Let me tell you why...");
}
}
Then in your controller simply call:
if (ModelState.IsValid) {
//You can only get this far if your Validate method
//doesn't return any ValidationResult objects.
//Do your magic!
}
Obviously this won't be executed client-side so if validation on the client is a requirement then you might need to roll that in.
One last note is that if you only have two values (e.g. Yes and No) a radio button may make more sense than a drop down.

Categories