bind and cascade dropdown list mvc 3 - c#

My view is
<div id="Countryy">
<div class="editor-label">
#Html.LabelFor(model => model.Country, "Country")
</div>
<div class="editor-field">
#Html.DropDownList("Country", String.Empty)
#Html.ValidationMessageFor(model => model.Country)
</div>
</div>
<div id="Statess">
<div class="editor-label">
#Html.LabelFor(model => model.State, "State")
</div>
<div class="editor-field">
#Html.DropDownList("State", String.Empty)
#Html.ValidationMessageFor(model => model.State)
</div>
</div>
<div id="Cityy">
<div class="editor-label">
#Html.LabelFor(model => model.City, "City")
</div>
<div class="editor-field">
#Html.DropDownList("City", String.Empty)
#Html.ValidationMessageFor(model => model.City)
</div>
</div
MY controller
public ActionResult Edit(int id)
{
Student student = db.Students.Single(s => s.ID == id);
ViewBag.Country = new SelectList(db.Couns, "ID", "CountryName", student.Country);
ViewBag.State = new SelectList(db.States.Where(d => d.CountryID.Equals(student.Country)), "StateID", "StateName", student.State);
ViewBag.City = new SelectList(db.Cities.Where(x => x.StateID.Equals(student.State)), "CityID", "CityName", student.City);
return View(student);
}
Blockquote
My question is how can i cascade the country ,state and city dropdown list.This view is generated when i want to edit the data.the saved data from db is retrived and binded to controls but when user changes the value of country dropdown than state dropdown should also be populated according to it.I have country,state,city 3 different tables in db with the required pk and fk

Here is the Solution for Country and State Cascading Dropdown in MVC using Ajax:-
First dropdown bind by retaining view bag by controller and for second drop down we can use JavaScript/Jquery to fill value based on selected country.
Below code used on cshtml page:
<div class="editor-label">
#Html.LabelFor(m => m.Country)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Country, new SelectList(Model.Country, "Value", "Text"), "Select Contry", new { onchange = "CountryChange()" })
</div>
<div class="editor-label">
#Html.LabelFor(m => m.State)
</div>
<div class="editor-field">
#Html.DropDownList("state","Select State")
</div>
We have used “CountryChange()” javascript function to fetch and fill data in state dropdown based on country change. Below is the JavaScript function implementation.
<script language="JavaScript" type="text/JavaScript">
function CountryChange () {
var url = '#Url.Content("~/Account/GetState")';
var ddlsource = "#Country";
var ddltarget = "#State";
if ($(ddlsource).val() != "") {
$.ajaxSetup({ cache: false });
$.getJSON(url, { Sel_Country: $(ddlsource).val() }, function (data) {
$(ddltarget).empty();
$("#State").append("<option value=''>Select State</option>");
$.each(data, function (index, optionData) {
$("#State").append("<option value='" + optionData.Value + "'>" + optionData.Text + "</option>");
});
});
}
else {
$("#State").empty();
$("#State").append("<option value=''>Select State</option>");
}
}
</script>
Here json url specified “~/Account/GetState” is method “GetState” available in “Account” controller to retrieve data and pass data in json format.
public JsonResult GetState (string Sel_Country)
{
CountryService db = new CountryService ();
JsonResult result = new JsonResult();
var vStateList = db.GetStateList(Convert.ToInt64(Sel_Country));
result.Data = vStateList.ToList();
result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
return result;
}

Related

There's some problem in "mixing ways" to do posts requests?

For example, in my project I'm using #using(Html.BeginForm(some stuff))to create an instance of my model and finally appending it to my database. But, when I'm editing (updating) some object of model, I'm usingn ajax get to retrieve data and finally using #Html.BeginForm() to post the update. Well, this is breaking some pattern of coding in MVC or whatever good principle?
Retrieving data and filling in the input fields
$.ajax({
url: "../../Obra/" + id,
type: "POST",
success: function(data) {
var obj = JSON.parse(JSON.stringify(data));
tit.value = obj.titulo;
ed.value = obj.editora;
obj.autores.forEach(x => {
var newn = divAutor.appendChild(aut.cloneNode());
newn.value = x;
});
img.value = obj.imagem;
divAutor.removeChild(aut);
},
error: function() {
alert('Error.');
}
});
All modal:
<div class="modal" id="modalOverlay">
<div class="modal-content" id="modalContent">
<header class="modal-header">
<h1 id="updateObraModalTitulo"></h1>
</header>
#using(#Html.BeginForm("Update", "Obra", FormMethod.Post, new { id="form-update" })) {
<div class="updateObraDivProp">
#Html.LabelFor(m => m.Titulo, "Título:")
#Html.TextBoxFor(m => m.Titulo, new { #class="editInputValue", #id="editTituloInput" })
</div>
<div class="updateObraDivProp">
#Html.LabelFor(m => m.Editora, "Editora:")
#Html.TextBoxFor(m => m.Editora, new { #class="editInputValue", #id="editEditoraInput"})
</div>
<div class="updateObraDivProp">
#Html.LabelFor(m => m.Autores, "Autores:")
<div id="divInputAutores">
#Html.TextBoxFor(m => m.Autores, new { #class="inputPostValue", id="addAutoresInput"})
</div>
<div class="btnNewAutorOp">
<button type="button" id="btnAddAutor" onclick="addNewAutor()">+</button>
<button type="button" id="btnDeleteAutor" onclick="deleteNewAutor()">×</button>
</div>
</div>
<div class="updateObraDivProp">
#Html.LabelFor(m => m.Imagem, "Imagem:")
#Html.TextBoxFor(m => m.Imagem, new { #class="inputPostValue", #id="editImagemInput" })
</div>
<input type="submit">
}
</div>
</div>
Because I can't retrieve the Id property when I click in the modal with mvc (or maybe I can using partial views?), I'm using javascript to create a function with the param id and getting data with ajax and finally updating with form

Object Reference, Unable to find User ID

Within my project I am trying to change the users ability from only being able to "Edit" an address field to being able to "Create" and "Edit" if it already exist within the same view. I receive the following server error Click Here.
I then ran it through the debugger and received the following result Click Here Too!. I can see that my User ID is being passed as null in the controller which creates the server error. But after following Mr. Pratt advice I can see the User Id is being passed into the View I am unsure why this is happening or where I've made the mistake.
Controller
// GET: /UserProfile/Edit/5
public ActionResult Edit(int id)
{
var userProfile = db.UserProfiles.FirstOrDefault(up => up.UserId == id);
var query = from o in db.UserProfiles
where o.Address != null
select o;
ViewBag.Query = query;
// if the user is not an admin
if (!User.IsInRole("admin"))
{
// look up current user id
var currentUserId = (int)System.Web.Security.Membership.GetUser().ProviderUserKey;
// check to make sure that the user profile is attached to the currently logged in user
if (userProfile.UserId == currentUserId)
{
return View(userProfile);
}
else
{
throw new Exception("you cannot access a user profile that is not your own");
}
}
// the user is an admin, so let them view the profile
return View(userProfile);
}
View
#model YardLad.Models.Domain.UserProfile
#{
ViewBag.Title = "Edit Profile";
}
<h2>Edit Profile</h2>
#if (User.IsInRole("contractor") || User.IsInRole("contractor2"))
{
<style>
#content a {
color: cornflowerblue;
}
#content a:hover {
color: cornflowerblue;
}
</style>
}
<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>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
#Html.HiddenFor(m => m.UserId)
#Html.HiddenFor(m => m.AcceptSMS)
#Html.HiddenFor(m => m.IsActive)
#Html.HiddenFor(m => m.LastLoginDate)
#Html.HiddenFor(m => m.AddressId)
<div class="editor-label">
Name
</div>
<div class="editor-field">
#Html.EditorFor(m => m.FirstName)
#Html.ValidationMessageFor(m => m.FirstName)
</div>
<div class="editor-field">
#Html.EditorFor(m => m.LastName)
#Html.ValidationMessageFor(m => m.LastName)
</div>
<div class="editor-label">
#Html.LabelFor(m => m.Phone)
</div>
<div class="editor-field">
#Html.TextBoxFor(m => m.Phone)
#Html.ValidationMessageFor(m => m.Phone)
</div>
<div class="editor-label">
#Html.LabelFor(m => m.Mobile)
</div>
<div class="editor-field">
#Html.TextBoxFor(m => m.Mobile)
#Html.ValidationMessageFor(m => m.Mobile)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.DateOfBirth)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.DateOfBirth)
#Html.ValidationMessageFor(model => model.DateOfBirth)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Gender)
</div>
<div class="editor-field">
#Html.RadioButton("Gender", "male") male
#Html.RadioButton("Gender", "female") female
#Html.ValidationMessageFor(m => m.Gender)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AddressId, "Address")
</div>
var address = ViewContext.ViewData.ModelState["Address"];
if (address != null && address.Errors.Count() > 0)
{
#Html.ActionLink("Add a billing address", "Create", "Address",
new { returnUrl = "UserProfile/Edit", userId = Model.UserId }, null)
}
else
{
<div class="editor-field">
#Html.DisplayFor(m => m.Address.Line1)<br />
#*#if (Model.Address.Line2 != null && address.Any())
{
#Html.DisplayFor(m => m.Address.Line2)<br />
}*#
#Html.DisplayFor(m => m.Address.City), #Html.DisplayFor(m => m.Address.State.Abbreviation) #Html.DisplayFor(m => m.Address.PostalCode)
</div>
if (ViewBag.Query != null || ViewBag.Query != "" )
{
#Html.ActionLink("Add an address", "Create", "Address", new { id = Model.AddressId, returnUrl = "UserProfile/Edit", userId = Model.UserId }, null)
}
else
{
#Html.ActionLink("Edit address", "Create", "Address", new { id = Model.AddressId, returnUrl = "UserProfile/Edit", userId = Model.UserId }, null)
}
}
#*<div class="editor-field">
<span>#Html.CheckBoxFor(m => m.AcceptSMS)</span>
<span class="editor-label">
#Html.LabelFor(m => m.AcceptSMS, "Accept SMS Service")
</span>
<p style="width: 50%; min-width: 300px;">
this free service allows you to send and receive text updates for easier access to making payments, scheduling reoccurring services, rating services, etc.<br />
<span style="font-size: .9em; color: forestgreen;">standard SMS charges still apply (based on your mobile carrier and plan)</span>
</p>
</div>*#
<p>
<input type="submit" value="Save" />
</p>
}
<div>
#Html.ActionLink("Back to My Account", "MyAccount", "Account")
</div>
userProfile is null. You need to do proper null-checking:
var userProfile = db.UserProfiles.FirstOrDefault(up => up.UserId == id);
if (userProfile == null)
{
return new HttpNotFoundResult();
}

How do I get the value of my second dropdownlist in MVC4?

I've got these two cascading dropdown lists, they populate just fine. But when I hit submit I always gett NULL as the value of the second. My guess is that I have to do something with the javascript, but my skills in that department are seriously lacking. Please help!
Code removed, whole view added instead
I dont even have an HtmlHelper for the second dropdown, it just looks like this in the view:
Code removed, whole view added instead
Works just fine, I mean, it populates fine depending on what's chosen in the first dropdown. Maybe this is the part that needs alteration? The thing is I'm clueless.
EDIT:
This is the code that reads the information from the form and submits it to the database.
[HttpPost]
public ActionResult Returer(ReturerDB retur)
{
if (ModelState.IsValid)
{
db2.ReturerDB.AddObject(retur);
db2.SaveChanges();
return RedirectToAction("Returer");
}
return View("Returer");
}
EDIT2
The whole view code:
#model Fakturabolag.Models.ReturerDB
#{
ViewBag.Title = "Returer";
}
<script type="text/javascript" src="../../Scripts/jquery-1.7.1.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#bolag").prop("disabled", true);
$("#Kund").change(function () {
if ($("#Kund").val() != "- Välj bolag -") {
var options = {};
options.url = "/companies/getbolag";
options.type = "POST";
options.data = JSON.stringify({ country: $("#Kund").val() });
options.dataType = "json";
options.contentType = "application/json";
options.success = function (bolag) {
$("#bolag").empty();
for (var i = 0; i < bolag.length; i++) {
$("#bolag").append("<option>" + bolag[i] + "</option>");
}
$("#bolag").prop("disabled", false);
};
options.error = function () { alert("Fel vid bolagshämtning!"); };
$.ajax(options);
}
else {
$("#bolag").empty();
$("#bolag").prop("disabled", true);
}
});
});
</script>
<h2>Returer</h2>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Returer</legend>
<br /><br />
<div class="editor-label">
<b>Kund</b>
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Kund, ViewData["kundLista"] as SelectList)
#Html.ValidationMessageFor(model => model.Kund)
</div>
<div class="editor-label">
<b>Bolag</b>
</div>
<select id="bolag"></select>
<div class="editor-label">
<b>Pris</b>
</div>
<div class="editor-field">
#Html.TextBox("pris", null, new { style = "width: 150px" })
#Html.ValidationMessageFor(model => model.Pris)
</div>
<div class="editor-label">
<b>Datum</b>
</div>
<div class="editor-field">
#Html.TextBox("datum", ViewData["datum"] as String, new { style = "width: 150px" })
#Html.ValidationMessageFor(model => model.Datum)
</div>
<p>
<input type="submit" value="Lägg till" />
</p>
</fieldset>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Currently you are not retrieving the additional value "bolag" in your action. I guess your model does not have property named "bolag". You can either add that or you can add additional parameter to you action like so:
[HttpPost]
public ActionResult Returer(ReturerDB retur, string bolag)
{
if (ModelState.IsValid)
{
db2.ReturerDB.AddObject(retur);
db2.SaveChanges();
return RedirectToAction("Returer");
}
return View("Returer");
}
After that, the selected value from the dropdown should automatically be in the bolag-parameter.
Edit.
You also need to add name-attribute to your select:
<select id="bolag" name="bolag"/>

MVC 4 Optimistic concurrency exception

Having faced this issue (I wanted to allow an edit by using a bootstrap modal window, i'm using MVC4 and entity framework), when I want to save my changes, I have this error message since I'm using the modal window :
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
Here are my actions :
[HttpGet]
public ActionResult EditPerson(long id)
{
var person = db.Persons.Single(p => p.Id_Person == id);
ViewBag.Id_ProductPackageCategory = new SelectList(db.ProductPackageCategories, "Id_ProductPackageCategory", "Name", person.Id_ProductPackageCategory);
return PartialView("_EditPerson", person);
}
[HttpPost]
public ActionResult EditPerson(Person person)
{
ViewBag.Id_ProductPackageCategory = new SelectList(db.ProductPackageCategories, "Id_ProductPackageCategory", "Name", person.Id_ProductPackageCategory);
if (ModelState.IsValid)
{
ModelStateDictionary errorDictionary = Validator.isValid(person);
if (errorDictionary.Count > 0)
{
ModelState.Merge(errorDictionary);
return View(person);
}
db.Persons.Attach(person);
db.ObjectStateManager.ChangeObjectState(person, EntityState.Modified);
db.SaveChanges();
return View("Index");
}
return View(person);
}
My partial view :
#model BuSIMaterial.Models.Person
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Edit</h3>
</div>
<div>
#using (Ajax.BeginForm("EditPerson", "Person", FormMethod.Post,
new AjaxOptions
{
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
UpdateTargetId = "table"
}))
{
#Html.ValidationSummary()
#Html.AntiForgeryToken()
<div class="modal-body">
<div class="editor-label">
First name :
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.FirstName, new { maxlength = 50 })
#Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
Last name :
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.LastName, new { maxlength = 50 })
#Html.ValidationMessageFor(model => model.LastName)
</div>
<div class="editor-label">
National number :
</div>
<div class="editor-field">
#Html.EditorFor(model => model.NumNat, new { maxlength = 11 })
#Html.ValidationMessageFor(model => model.NumNat)
</div>
<div class="editor-label">
Start date :
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.StartDate, new { #class = "datepicker", #Value = Model.StartDate.ToString("yyyy/MM/dd") })
#Html.ValidationMessageFor(model => model.StartDate)
</div>
<div class="editor-label">
End date :
</div>
<div class="editor-field">
#if (Model.EndDate.HasValue)
{
#Html.TextBoxFor(model => model.EndDate, new { #class = "datepicker", #Value = Model.EndDate.Value.ToString("yyyy/MM/dd") })
#Html.ValidationMessageFor(model => model.EndDate)
}
else
{
#Html.TextBoxFor(model => model.EndDate, new { #class = "datepicker" })
#Html.ValidationMessageFor(model => model.EndDate)
}
</div>
<div class="editor-label">
Distance House - Work (km) :
</div>
<div class="editor-field">
#Html.EditorFor(model => model.HouseToWorkKilometers)
#Html.ValidationMessageFor(model => model.HouseToWorkKilometers)
</div>
<div class="editor-label">
Category :
</div>
<div class="editor-field">
#Html.DropDownList("Id_ProductPackageCategory", "Choose one ...")
#Html.ValidationMessageFor(model => model.Id_ProductPackageCategory) <a href="../ProductPackageCategory/Create">
Add a new category?</a>
</div>
<div class="editor-label">
Upgrade? :
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Upgrade)
#Html.ValidationMessageFor(model => model.Upgrade)
</div>
</div>
<div class="modal-footer">
<button class="btn btn-inverse" type="submit">Save</button>
</div>
}
Any idea on what's going on?
Try this first, just above #Html.ValidationSummary() in the partial view where you have the modal head, body and footer, place:
#Html.HiddenFor(model => model.PersonId) // or.Id whatever's in your model
This creates a hidden field in your view and sets model ID i.e. PK.

Implementing Search criteria using MVC return no record

I am trying to implement search criteria which bind to Kendo Ui grid. However it return no record and no error display. In SearchProduct it return the data but it would not bind to grid
Is there something i missed?
Controller code :
[HttpPost]
public ActionResult SearchProduct(ProductSearchCriteria criteria)
{
string nameCriteria = string.Empty;
string descCriteria = string.Empty;
TTSEntities dc = new TTSEntities();
if (!string.IsNullOrWhiteSpace(criteria.Name))
nameCriteria = criteria.Name.ToLower().Trim();
if (!string.IsNullOrWhiteSpace(criteria.Community))
descCriteria = criteria.Desc.ToLower().Trim();
var results = dc.Products.AsQueryable();
if (criteria.Name!= null)
results = results.Where(b => b.Name== criteria.Name);
if (criteria.Desc!= null)
results = results.Where(b => b.Desc== criteria.Desc);
return PartialView("_ProductGrid", results.ToList());
}
Index.cshtml :
#model HHIMS_Web_App.Models.ProductSearchCriteria
#using (Html.BeginForm())
{
<div id="headerpanel">
<fieldset>
<legend style="font-size:14px">Search Criteria</legend>
<div>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
</div>
</div>
<div>
<div class="editor-label">
#Html.LabelFor(model => model.Desc)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Desc)
</div>
<div class="smallBox">
<input type="button" value="Search" id="btnProductSearch" style="height:33px; font-size:14px; background-color:#3399FF" class="k-button" />
</div>
</div>
</fieldset>
</div>
}
<script type="text/javascript">
$(document).ready(function () {
$('#btnProductSearch').click(function (e) {
var searchParameters = GetSearchParameters();
var jsonData = JSON.stringify(searchParameters, null, 2);
$.ajax({
url: '#Url.Content("~/ProductDetails/SearchProduct/")',
type: 'POST',
data: jsonData,
datatype: 'html',
contentType: 'application/json; charset=utf-8',
success: function (data) {
$('#btnProductSearch').replaceWith(data);
},
error: function (request, status, err) {
alert(status);
alert(err);
}
});
});
function GetSearchParameters() {
var hrn = $("#Name").val();
var community = $("#Desc").val();
return { Name: name,
Desc: desc
};
}
});
</script>
_ProductGrid View :
<div>
<fieldset class="searchResults">
<legend style="font-size:14px">Search Result</legend>
<br />
<div>
#(Html.Kendo().Grid<TTP.Models.ProductModel>()
.Name("Product")
.HtmlAttributes(new { #Style = "align:center; font-size:10px; width:500px" })
.Columns(columns =>
{
columns.Bound(p => p.Name);
columns.Bound(p => p.Desc);
})
.AutoBind(false)
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Sortable()
//.Pageable()
.Pageable(paging => paging
.Input(false)
.Numeric(true)
.PreviousNext(true)
.PageSizes(new int[] { 5, 10, 25, 50 })
.Refresh(false)
)
.Selectable()
.Scrollable()
.ColumnMenu(c => c.Columns(false))
.DataSource(dataSource => dataSource
.Ajax()//bind with Ajax instead server bind
.PageSize(10)
.ServerOperation(true)
.Model(model =>
{
model.Id(p => p.Name);
}
)
)
)
</div>
</fieldset>
</div>
Your SearchProduct action should return JSON data for the grid.
See the Kendo Grid Demo - choose the ASP.NET MVC tab and look at the IndexController.Products_Read code.
You want something like this:
public ActionResult SearchProduct(
ProductSearchCriteria criteria,
[DataSourceRequest] DataSourceRequest dsr
)
{
IQueryable<Product> query = ...
return Json( query.ToDataSourceResult( dsr ) );
}
To pass the search parameters as extra data with the read ajax request, use the Data method:
dataSource.Read( read => read.Data( "GetSearchParameters" ) )
See Kendo: Ajax Binding - Pass Additional Data to Action Method

Categories