The parameters dictionary contains a null entry for parameter id - asp.net-mvc-4

function GetStatevalue() {
var state_id= $("#ddlstate").val();
var city = $("#txtcity").val();
var datao = new Object();
datao={ state:state_id ,city_name: city }
var url = "/city/AddCity";
$.ajax({
url: url,
data:datao ,
cache: false,
type: "POST",
dataType: "json",
success: function (datao) {
},
error: function (reponse) {
alert("error : " + state_id);
}
});
Html Form
#Html.DropDownListFor(model => model.tbl_state.coutry_id, (SelectList)ViewBag.country_nm, "Select Country", new {#id="coutry_id" , #onchange="GetState(this.value)"})
<select id="ddlstate" name="ddlstate" style="width: 200px" >
#Html.TextBoxFor(model =>model.tbl_city.city_name ,new {#id="txtcity" })
<input type="submit" id="save" value="Add" name="actiong" onclick="GetStatevalue();" />
Controller
[HttpPost]
public ActionResult AddCity(int id,String city_name)
{
tbl_city data = new tbl_city();
data.city_name = city_name;
data.state_id = id;
db.tbl_city.Add(data);
db.SaveChanges();
return Json(data);
}
The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult AddCity(Int32, System.String)' in 'test_app.Controllers.cityController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter. Parameter name: parameters

After seeing your JqueryCode , you actionresult method should look like:
[HttpPost]
public ActionResult AddCity(int state,String city_name)
//bcoz{ state(action variablename):state_id ,city_name(action variablename): city }
{
tbl_city data = new tbl_city();
data.city_name = city_name;
data.state_id = id;
db.tbl_city.Add(data);
db.SaveChanges();
return Json(data);
}

Related

When adding a new dynamic row with partial views, all rows cleared after deleting one

When the user adds an item to a list everything works fine until you delete an entry. The row gets deleted but once you add a new row, all rows are deleted with the new row added. The issue is that once you delete a row and add a new one it loads from the database, if you haven't saved the order yet everything entered is lost.
Is there a way to delete, then add, without saving the order every time you delete an item?
Js delete function
function del(e, id) {
e.currentTarget.parentElement.parentElement.remove()
if (id === 0) {
var row = $(this).closest(".tablerow0");
row.remove();
} else {
$.ajax({
url: '/Business/Order/DeleteOrderItem',
data: {
id: id
},
contentType: 'application/json',
success: function (data) {
},
error: function (e) {
console.log(e)
}
})
}
}
HTML
<div id="orderItemsContainer" style="width: 100%;float: left;">
#Html.EditorFor(model => model.Items)
</div>
Add Item
//Add new item
$(document).on('click', '#btnAdd', 'click', function (e) {
$.ajax({
async: true,
data: $('#forming').serialize(),
type: "POST",
url: '/Business/Order/AddOrderItem',
success: function (partialView) {
console.log("partialView: " + partialView);
$('#orderItemsContainer').html(partialView);
}
});
});
Html delete button
<button type="button" tabindex="-1" class="btntext-danger font-weight-bold clear-item" title="Remove" asp-action="DeleteOrderItem" asp-route-id="#Model.Id" asp-area="Business"
onClick="$(this).closest('.tablerow0').remove(); Update(); del(event, #Model.Id);showHideBtn()">
Controller
public IActionResult DeleteOrderItem(int id, [Bind("Items")] Order order)
{
if (id == 0)
{
return PartialView("Item", order);
}
var itemToDelete = _db.Items.Find(id);
_db.Remove(itemToDelete);
_db.SaveChanges();
return Json(itemToDelete);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> AddOrderItem([Bind("Items")] Order order)
{
order.Items.Add(new Item());
return PartialView("Item", order);
}
public IActionResult DeleteOrderItem(int id, [Bind("Items")] Order order)
{
if (id == 0)
{
return PartialView("Item", order);
}
var itemToDelete = _db.Items.Find(id);
_db.Remove(itemToDelete);
_db.SaveChanges();
return Json(itemToDelete);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> AddOrderItem([Bind("Items")] Order order)
{
order.Items.Add(new Item());
return PartialView("Item", order);
}
Check the above code, when add items, the items are not inserted into the database, but when you delete items, it will delete items from the database. So, the issue might relate that.
You could refer the comment to modify your code:
public IActionResult DeleteOrderItem(int id, [Bind("Items")] Order order)
{
if (id == 0)
{
return PartialView("Item", order);
}
//1. delete items from database.
var itemToDelete = _db.Items.Find(id);
_db.Remove(itemToDelete);
_db.SaveChanges();
//2. query database get the latest items:
var result = _db.Items.ToList();
//then return the items to the main page and display them
return Json(result);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> AddOrderItem([Bind("Items")] Order order)
{
//1. insert the items into database.
//2. query the database, get the latest items.
//3. add a new Item instance, to let use enter the new value.
order.Items.Add(new Item());
return PartialView("Item", order);
}

RadioButton list Binding in MVC4

I have a radiobuttonList which is binding data from Enum Class and its working correctly in the view.
But my concern is how can I set inital value of radiobutton to CROCount.ONE.I have tried to set the initial value in the following way but couldnot get the desired result.
public enum CROCount
{
ONE = 1,
TWO = 2
}
ViewModel is
public class RegistraionVM
{
....
public EnumClass.CROCount CROCount { get; set; }
}
I generated the radio button list as follows.
<div>
#foreach (var count in Enum.GetValues(typeof(SMS.Models.EnumClass.CROCount)))
{
<label style="width:75px">
#Html.RadioButtonFor(m => m.RegistrationVenue, (int)count,
new { #class = "minimal single" })
#count.ToString()
</label>
}
</div>
Binding performed in the Controller is
public ActionResult Index(int walkInnId)
{
try
{
var _studentReg = new RegistraionVM
{
CROCount=EnumClass.CROCount.ONE
};
return View(_studentReg);
}
catch (Exception ex)
{
return View("Error");
}
}
Your binding your radio button to property CROCount (not RegistrationVenue) so your code should be
#Html.RadioButtonFor(m => m.CROCount, count, new { id = "", #class = "minimal single" })
Note that the 2nd parameter is count (not (int)count) so that you generate value="ONE" and value="TWO". Note also the new { id = "", removes the id attribute which would otherwise result in duplicate id attributes which is invalid html.

MVC4 ViewData.TemplateInfo.HtmlFieldPrefix generates an extra dot

I'm trying to get name of input correct so a collection of objects on my view model can get bound.
#{ViewData.TemplateInfo.HtmlFieldPrefix = listName;}
#Html.EditorFor(m => m, "DoubleTemplate", new {
Name = listName,
Index = i,
Switcher = (YearOfProgram >= i +1)
})
As you can see here, I pass in the "listName" as the prefix for my template, the value of listName = "MyItems".
And here is my template:
#model Web.Models.ListElement
#if (ViewData["Switcher"] != null)
{
var IsVisible = (bool)ViewData["Switcher"];
var index = (int)ViewData["Index"];
var thisName = (string)ViewData["Name"] + "[" + index + "].Value";
var thisId = (string)ViewData["Name"] + "_" + index + "__Value";
if (IsVisible)
{
#*<input type="text" value="#Model.Value" name="#thisName" id ="#thisId" class="cell#(index + 1)"/>*#
#Html.TextBoxFor(m => m.Value, new { #class ="cell" + (index + 1)})
#Html.ValidationMessageFor(m => m.Value)
}
}
but I found that the generated name becomes this: MyItems.[0].Value
It has one extra dot. How can I get rid of it?
Incidentally, I tried to manually specify the name inside the template and found the name gets overridden by the Html helper.
Update
The reason why I have to manually set the HtmlFieldPrefix is the property name (MyItems which is a list of objects) will get lost when MyItems is passed from main view to the partial view. By the time, the partial view called my template and passed in one object in MyItems, the template itself has no way to figure out the name of MyItems as it has been lost since the last "pass-in".
So that's why I have to manually set the html field prefix name. And I even tried to use something similar to reflection(but not reelection, I forgot the name) to check the name of passed in object and found it returned "Model".
Update 2
I tried Stephen's approach, and cannot find the html helper PartialFor().
I even tried to use this in my main view:
Html.Partial(Model, "_MyPartialView");
In Partial View:
#model MvcApplication1.Models.MyModel
<h2>My Partial View</h2>
#Html.EditorFor(m => m.MyProperty)
Here is my templat:
#model MvcApplication1.Models.ListElement
#Html.TextBoxFor(m => m.Value)
Here is my Model:
public class MyModel
{
private List<ListElement> myProperty;
public List<ListElement> MyProperty
{
get
{
if (myProperty == null)
{
this.myProperty = new List<ListElement>() { new ListElement() { Value = 12 }, new ListElement() { Value = 13 }, new ListElement() { Value = 14 }, new ListElement() { Value = 15 }, };
}
return this.myProperty;
}
set
{
this.myProperty = value;
}
}
}
public class ListElement
{
[Range(0, 999)]
public double Value { get; set; }
}
And here is my controller:
public ActionResult MyAction()
{
return View(new MyModel());
}
It only generates raw text("12131415") for me, instead of the wanted text box filled in with 12 13 14 15.
But if I specified the template name, it then throws an exception saying:
The template view expecting ListElement, and cannot convert
List<ListElement> into ListElement.
There is no need set the HtmlFieldPrefix value. MVC will correctly name the elements if you use an EditorTemplate based on the property type (and without the template name).
Assumed models
public class ListElement
{
public string Value { get; set; }
....
}
public class MyViewModel
{
public IEnumerable<ListElement> MyItems { get; set; }
....
}
Editor template (ListElement.cshtml)
#model YourAssembly.ListElement
#Html.TextBoxFor(m => m.Value)
Main view
#model YourAssembly.MyViewModel
...
#Html.EditorFor(m => m.MyItems) // note do not specify the template name
This will render
<input type="text" name="MyItems[0].Value" ...>
<input type="text" name="MyItems[1].Value" ...>
....
If you want to do this using a partial, you just can pass the whole model to the partial
MyPartial.cshtml
#model #model YourAssembly.MyViewModel
#Html.EditorFor(m => m.MyItems)
and in the main view
#Html.Partial("MyPartial")
or create an extension method
public static MvcHtmlString PartialFor<TModel, TProperty>(this HtmlHelper<TModel> helper,
Expression<Func<TModel, TProperty>> expression, string partialViewName)
{
string name = ExpressionHelper.GetExpressionText(expression);
object model = ModelMetadata.FromLambdaExpression(expression, helper.ViewData).Model;
var viewData = new ViewDataDictionary(helper.ViewData)
{
TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = name }
};
return helper.Partial(partialViewName, model, viewData);
}
}
and use as
#Html.PartialFor(m => m.MyItems, "MyPartial")
and in the partial
#model IEnumerable<YourAssembly.ListElement>
#Html.EditorFor(m => m)
Call your partial this way:
#Html.Partial("_SeatTypePrices", Model.SeatTypePrices, new ViewDataDictionary
{
TemplateInfo = new TemplateInfo() {HtmlFieldPrefix = nameof(Model.SeatTypePrices)}
})
Partial view:
#model List
#Html.EditorForModel()
Editor template implementation:
#using Cinema.Web.Helpers
#model Cinema.DataAccess.SectorTypePrice
#Html.TextBoxFor(x => Model.Price)
This way your partial view will contain list of items with prefixes.
And then call EditorForModel() from your EditorTemplates folder.
I found that I can change the value of HtmlFeildPrefix in my template.
So what I did to solve my problem was just to assign the correct value to HtmlFeildPrefix in the template directly rather than in the page which calls the template.
I hope it helps.
If I want to pass the HtmlFieldPrefix I use the following construct:
<div id="_indexmeetpunttoewijzingen">
#Html.EditorFor(model => model.MyItems, new ViewDataDictionary()
{
TemplateInfo = new TemplateInfo()
{
HtmlFieldPrefix = "MyItems"
}
})
</div>

MVC4: Model's properties are null - 2

For some reason, when I press any of the buttons of my view, all properties of the model passed to the action method are null:
View:
#using (Html.BeginForm("FolderChange", "EdiSender", FormMethod.Post, new {id = "ediFilesForm"}))
{
var directoriesSelectList = new SelectList(Model.Directories);
#Html.DropDownListFor(m => m.SelectedDirectory, directoriesSelectList, new {#Id = "Directories", #style = "width:Auto;", #size = 20, onchange = "$('#ediFilesForm').submit()", name = "action:FolderChange"})
var ediFilesSelectList = new SelectList(Model.EdiFileNames);
#Html.DropDownListFor(m => m.SelectedEdiFile, ediFilesSelectList, new {#Id = "EdiFileNames", #style = "width:Auto;", #size = 20})
}
<br/>
...
<form action="" method="post">
<input type="submit" value="Send" name="action:Send" />
<input type="submit" value="Delete" name="action:Delete" />
<input type="submit" value="Refresh" name="action:Refresh" />
</form>
Controller:
[HttpPost]
[MultipleButton(Name = "action", Argument = "Send")]
public ActionResult Send(EdiFileModel ediFileModel)
{
....
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MultipleButtonAttribute : ActionNameSelectorAttribute
{
public string Name { get; set; }
public string Argument { get; set; }
public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
{
var isValidName = false;
var keyValue = string.Format("{0}:{1}", Name, Argument);
var value = controllerContext.Controller.ValueProvider.GetValue(keyValue);
if (value != null)
{
controllerContext.Controller.ControllerContext.RouteData.Values[Name] = Argument;
isValidName = true;
}
return isValidName;
}
}
It used to work when my buttons were within the Html.BeginForm() block, but I cannot have it like that anymore, because it has now action name as FolderChange(), which is different from e.g. Send() or other action method that handles button press.
Thanks.
EDITED:
#section scripts
{
<sctipt type="text/javascript">
$("#Directories").change(function () {
var selectedDirectory = $("#Directories").val();
$(function () {
$.getJSON('/DoWork/FolderChangeAjaxCall?selectedDirectory=' + selectedDirectory, function (result) {
var ddl = $('#EdiFileNames');
ddl.empty();
$(result).each(function () {
$(document.createElement('option'))
.attr('value', this.Id)
.text(this.Value)
.appendTo(ddl);
});
});
});
});
</sctipt>
}
<h2>Existing EDI Files</h2>
#using (Html.BeginForm("FolderChange", "EdiSender", FormMethod.Post, new {id = "ediFilesForm"}))
{
var directoriesSelectList = new SelectList(Model.Directories);
#Html.DropDownListFor(m => m.SelectedDirectory, directoriesSelectList, new {#Id = "Directories", #style = "width:Auto;", #size = 20})
var ediFilesSelectList = new SelectList(Model.EdiFileNames);
#Html.DropDownListFor(m => m.SelectedEdiFile, ediFilesSelectList, new {#Id = "EdiFileNames", #style = "width:Auto;", #size = 20})
Here it is, it's probably way off from what you thought the answer would be, but it will cascade the dropdowns. Your going to have to substitute your values and context in, but it will work. Now you can place your buttons in the form and not have to have the dropdown's submit the form, which is pretty poor design anyways.
#Html.DropDownListFor(x => x.ddlID, Model.myDDLList, new { id = "ddl" })
#Html.DropDownListFor(x => x.myDDLList2, Model.myDDLList2, new { id = "foo" })
Script
$("#ddl").change(function () {
var Id = $("#ddl").val(); //1st dropdown Value
$(function () {
$.getJSON('/DoWork/AjaxCall?Id=' + Id, function (result) {
var ddl = $('#foo');
ddl.empty();
$(result).each(function () {
$(document.createElement('option'))
.attr('value', this.Field1)
.text(this.Field2)
.appendTo(ddl);
});
});
});
});
Controller
public ActionResult AjaxCall(int Id)
{
using (PerformanceEntities context = new PerformanceEntities())
{
return this.Json(
(from obj in context.ACCOUNT.Where(x => x.ACCT_ID == Id).ToList()
select new
{
Field1 = obj.ACCT_ID,
Field2 = obj.ACCT_NAME
}),
JsonRequestBehavior.AllowGet
);
}
}
You can check out this post for reference

MVC4 Dropdownlist

I need to pass values from three dropdownlists to the controller when user selects some value from any one of the dropdownlist.i tried like this but the value from only the dropdown selected is passed others are null values ,any help would be appreciated.
VIEW
##using (Html.BeginForm("GetFilterValues","Home",FormMethod.gET))
{
#Html.DropDownList("FClass", ViewBag.Market as SelectList, new { id = "Market" , onchange = "$(this).parents('form').submit();" })
}
#using (Html.BeginForm("GetFilterValues","Home",FormMethod.Get))
{
#Html.DropDownList("FClass", ViewBag.Class as SelectList, new { id = "FClass" , onchange = "$(this).parents('form').submit();" })
}
</td>
<td>
#Html.Label("Status")
</td>
<td>
#using (Html.BeginForm("GetFilterValues","Home",FormMethod.Get))
{
#Html.DropDownList("Status", ViewBag.Status as SelectList, new { id = "Status" , onchange = "$(this).parents('form').submit();" })
}
CONTROLLER
[HttpgET]
public void GetFilterValues()
{
string market = this.Request.Form.Get("Market");
string fclass = this.Request.Form.Get("FClass");
string status = this.Request.Form.Get("Status");
}
Try a single form trough a POST and pull the values by name using a FormCollection like this...
View:
#using (Html.BeginForm("GetFilterValues","Home", FormMethod.Post))
{
#Html.DropDownList("nameMarket", ViewBag.Market as SelectList, new { id = "Market" , onchange = "$(this).parents('form').submit();" })
#Html.DropDownList("nameClass", ViewBag.Class as SelectList, new { id = "FClass" , onchange = "$(this).parents('form').submit();" })
#Html.DropDownList("nameStatus", ViewBag.Status as SelectList, new { id = "Status" , onchange = "$(this).parents('form').submit();" })
}
Controller:
[HttpPost]
public void GetFilterValues(FormCollection collection) {
string market = Convert.ToString(collection["nameMarket"]);
string fclass = Convert.ToString(collection["nameClass"]);
string status = Convert.ToString(collection["nameStatus"]);
}