DropDownList Error, System.InvalidOperationException - c#

Create.cshtml
#Html.DropDownList("KategoriId",null,htmlAttributes: new { #class="form-control"})
MakaleController.cs
public ActionResult Create()
{
ViewBag.KategoriId = new SelectList(db.Kategoris, "KategoriId", "KategoriAdi");
return View();
}
but it's say When I make a post request,
The ViewData element with the 'KategoriId' key is of type 'System.Int32', but of type 'IEnumerable '.
How to fix this error, I tried many ways but it did not happen. He says that the value is generally null.
Kategori.cs (!! NOT KATEGORIS, i create with code first)
[Table("Kategori")]
public partial class Kategori
{
public int KategoriId { get; set; }
[StringLength(50)]
public string KategoriAdi { get; set; }
public virtual Makale Makale { get; set; }
}

Updated
Your dropdown definition is not right
it should look like below
#Html.DropDownListFor(m => m.CategoryID, Model.CategoryList, "-Please select-")
you pass null to Dropdownlist, but it is supposed to be at least an empty list
You also try to keep dropdownlist data in viewbag. it is supposed to be a List property in the view model.
P.S: using native words in variable names are not acceptable in global projects due to readability issues =)
P.S: You can check a similar question and answer from here The ViewData item that has the key 'XXX' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'

Related

Referencing Complex Enumerable in Razor [duplicate]

This question already has answers here:
ASP.NET MVC: No parameterless constructor defined for this object
(28 answers)
Closed 4 years ago.
Why isn't MVC able to bind my List of complex objects? I have read several examples on this topic and nothing has resolved the issue. Consider the following:
Complex Version
I have a ViewModel with a list of complex objects as a property:
public List<XMLVariable> XMLVariables { get; set; }
My View then binds this list of objects to controls:
#for (int i = 0; i < Model.XMLVariables.Count(); i++)
{
#Html.HiddenFor(m => Model.XMLVariables[i].Name)
#Html.TextBoxFor(m => Model.XMLVariables[i].Value)
}
The view displays the variables just fine, but when I submit the form nothing happens. The controller action is not called.
Flattened Version
If I flatten my list of complex objects (XMLVariables) in the same ViewModel:
public List<string> Names { get; set; }
public List<string> Values { get; set; }
And map them in my View:
#for (int i = 0; i < Model.XMLVariables.Count(); i++)
{
#Html.HiddenFor(m => Model.Names[i])
#Html.TextBoxFor(m => Model.Values[i])
}
Upon submission both lists are passed back with the correct values.
Controller Action:
[HttpPost]
public ActionResult Submit(ReportViewModel report, string cmd)
{
}
Form Signature:
#using (Ajax.BeginForm("Submit", "Report", new AjaxOptions {LoadingElementId = "progress", OnSuccess="OnSuccess", OnBegin="OnBegin", OnComplete="OnComplete" }))
The problem was with my "XMLVariable" object. In case anyone has an issue binding custom objects like I did, it appears that MVC constructs a new ViewModel out of the data in the View, rather than passing back a modified version.
I wasn't getting an error for some reason, but the default model binder in MVC was creating XML objects from scratch and trying to call a parameterized constructor I had set up:
public class XMLVariable
{
public string Name {get; set;}
public string Value { get; set; }
//MVC needed this parameterless constructor to bind View to new ViewModel
public XMLVariable()
{ }
//This was getting called before adding the parameterless constructor and failing
public XMLVariable(string name, string value)
{
Name = name;
Value = value;
}
}
Thank you to ChetanRanpariya for pointing me to the network tracing tool that caught the issue.
If someone has the reputation for it, please mark this as a duplicate of this question which I found after the fact.

Loop over ModelView in razor

I have created razor forms that do a #foreach to loop over the model and produce my rows. Now I am trying to to the same thing over a ViewModel, and I get the following error.
Unable to create a constant value of type 'MyProject.Models.SupportContact'.
Only primitive types or enumeration types are supported in this context.
My #model is being passed in as IQueryable(MyProject.Models.SupportContactFormView), and SupportContact is part of that ViewModel, but I can't seem to reference it in the model.
I can do this:
#foreach (var item in Model ) {
#Html.DisplayFor(modelItem => item.SupportContact.Contact)
But then I will get the error above when it actually try to process my cshtml. I have tried to do:
#foreach (MyProject.Models.SupportContact item in Model ) {}
But I can't drill down thru the model to get the SupportContacts. How can I get to a my SupportContact class inside my ViewModel?
Thanks
Edit:
Here is the ViewModel declaration:
public class SupportContactFormView
{
public SupportContact SupportContact { get; private set; }
public SelectList Priorities { get; private set; }
public SelectList ContactTypes { get; private set; }
public String Group_COde { get; private set; }
}
In your case, I would create a viewmodel specifically for that view and set it up like so
ViewModel Class
public class IndexViewModel
{
public IList<SupportContact > SupportContacts { get; set; }
}
Controller
public ActionResult Index()
{
var viewModel = new IndexViewModel();
viewModel.SupportContacts = IQueryableListOfContacts.ToList();
return View(viewModel)
}
View
#model IndexViewModel
#foreach (var contact in Model.SupportContacts) {
#Html.DisplayFor(_ => contact.Contact)
You need to play around a bit with the code, as I doubt I have the property names/action method name correct first time, but I hope you get the basic idea. Create a viewmodel class that the view file makes use of, and dump the contact details into a List. That will make it easier for you.
EDIT:
Actually, I think I got the wrong end of the stick here. The error "Unable to create a constant value of type 'MyProject.Models.SupportContact'.
Only primitive types or enumeration types are supported in this context." means that there is something wrong with your LINQ data.
Are you using Entity Framework or Linq2SQL? Ignore my answer about the viewmodel appraoch, your actual issue is LINQ related. Try iterating over the list of contacts in an ActionMethod instead e.g.
public ActionMethod Index()
{
foreach (var contact in whateveryourcontactslistis) {
}
// ....
}
If you still have a problem here, then it's your LINQ data at fault.

An object used as a model in a partial view creates another in the controller?

There is something weird going on in my app. It's not dammageable, but it's a curious behavior and I'm reaching out to you to understand what's happening.
I was working on some partial view based on a model, and it worked. I figured out I had to replace a lot of stuff with the correct input.
So here's a snippet of my old model:
public class SearchObjInfo
{
public string m_ObjName { get; set; }
public string m_ObjType { get; set; }
public decimal? m_ObjNumber { get; set; }
public string m_ObjSymbol { get; set; }
public string m_ObjPower { get; set; }
}
And here's the same snippet with the new class I made to construct this partial view:
public class SearchObjInfoPartial
{
public string m_ObjName { get; set; }
public IEnumerable<SelectListItem> m_ObjType { get; set; }
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:0}")]
public int m_ObjNumber { get; set; }
public IEnumerable<SelectListItem> m_ObjPower { get; set; }
public IEnumerable<SelectListItem> m_ObjSymbol { get; set; }
}
Now the way the render is made is actually quite identical, and not. I used lots of stuff like these before:
<label>
Text: Write a name, part of a name, or a word.
</label>
Object Name: #Html.TextBox("_objectName") <br/>
Object Number: <input type="number" min="0" max="9999" name="_objNumber" value="decimal" style="width: 70px"/><br/>
Type: #Html.DropDownList("_objType", "All") <br/>
Power: #Html.DropDownList("_objSymbol", "=") #Html.DropDownList("_objValue", String.Empty)<br/>
But now I render my partial view this way:
#model MyApp.Utilities.SearchObjInfoPartial
Object Name: #Html.TextBoxFor(item => item.m_ObjName, Model.m_ObjName, String.Empty) <br/>
Object Number: #Html.EditorFor(item => item.m_ObjNumber)<br />
Power: #Html.DropDownListFor(item => item.m_ObjPower, Model.m_ObjPower, String.Empty) #Html.DropDownListFor(item => item.m_ObjSymbol, Model.m_ObjSymbol, String.Empty)
Type: #Html.DropDownListFor(item => item.m_ObjType, Model.m_ObjType, String.Empty) <br/>
Before rendering I deal with the SelectLists, no problems here.
Now here's where it gets interesting:
In my controllers I used to have methods receiving huge amounts of data (see here: How to deal with many possible values to make a query?)
But now I made something else. Without thinking, I tried to add the old search model in the controller method like this:
public ActionResult BrowseObjectList(SearchObjInfo searchObj, string _objName, (...))
And I just found out that it works even if the receiving object is not the same as the one used in my partial view model. How is that even possible? I mean, the proper fields will fill up and I can "safely" deal with my searchObj item, though I do not find this secure after all...
Thats what MVC framework does for you man.
Browser simply sends the form collection to server as Name Value Collection. As the request hits server, MVC framework will match the values with parameter in the Action method.
Form collection values are mapped to Model object properties. This is done by doing a match with Property Name and Name of the value in Form collection. Just check the client side code by view source, you can see that the input tags will have an attribute 'name' which matches with the property name of model.
QueryString values will also be mapped to parameters in Action method based on name.
Even you add a hidden field and specify a parameter with same name in action method...tada you will get the value of hidden field in that variable on post back
In your case though the model is different, its property name are same m_ObjName, m_ObjType, m_ObjNumber, m_ObjSymbol, m_ObjPower. So MVC do a match for you.
Try with different property name and see the results ;-)

using ViewBag to pass a model object

I'm trying to sort my result page (which is in another view than the filtration page). I have faced this weird issue I do not understand why keeps happening to me.
All the codes provided in very short form, please ask me if you need any other parts of my code for more information.
My Index view(where user filters results):
#model IEnumerable<Cars.Models.CarSearch>
#using (Html.BeginForm("SearchResult", "Home", FormMethod.Post,
new
{
id = "CategoryFormID",
data_modelListAction = #Url.Action("ModelList"),
data_makeListAction = #Url.Action("MakeList"),
data_editionListAction = #Url.Action("EditionList")
}))
{
<label>Make</label>
<select id="MakeID" name="carMake">
<option>All Makes</option>
</select>
}
My SearchResult view:
#model IEnumerable<Cars.Models.Car>
Make
My model:
public class Car
{
public String Make { get; set; } //is my table model
}
public class CarFilter {
public String carMake { get; set; }
}
public class CarSearch {
public CarFilter CarFilter { get; set; }
public byte PageSize { get; set; }
public short PageNumber { get; set; }
public int TotalRows { get; set; }
}
My Controller:
public ActionResult SearchResult(String sortOrder, CarFilter filters)
{
ViewBag.CurrentFilters = filters;
return View();
}
All I'm trying to do is to get carMake from Index post it to controller in CarFilter form (since in my code there are LOTS of fields in the form and I don't want to write them all down) and when user clicks on sort by Make it GET the SearchResult method and it's supposed to set filters = ViewBag.CurrentFilters which is the value user inputted from beginning.
Now the funny part is, when I replace CarFilter filters with String carMake and other places respectively. It works like a charm.
My question:
Why?
How can I do this with CarFilter filters?
UPDATE:
Problem is that filters = ViewBag.CurrentFilters in my SearchResult view does not work with the type CarFilter, because it keeps giving me NULL value when user clicked on the sort by Make.
Second UPDATE:
I tried changing filters = ViewBag.CurrentFilters with CarFilter = ViewBag.CurrentFilters. Now CarFilter filters in my SearchResult(...)method in my controller is not and null object, but ALL the values of the objects in the model class is null (which shouldn't be). I mean the filters object exists but it seems like the values of CarFilter class in my model haven't been passed by ViewBag.CurrentFilters to the view.
when you canged the name it worked because framework found property name and the bind it to what you have within action parameters doesnt work so nicely with objects. My advice is to stick with simple types
Here is similiar case:
How to send model object in Html.RenderAction (MVC3)
Its not a ViewBag problem thants how it works in general. Its the prime reason for using flatted models :/

ASP.NET MVC Forms for Model

I'm trying to learn MVC by building a full-featured website. I'm a little stuck when it comes to dealing with forms, and posting data, and models....
BTW: I'm using EF Code-First w/MS SQL CE
Here's the Models in question:
public class Assignment
{
public int AssignmentID { get; set; }
public int? CourseID { get; set; }
public string Name { get; set; }
// etc...
public virtual Course Course { get; set; }
}
public class Course
{
public int CourseID { get; set; }
// etc...
}
I'm loading a partial view that allows the user to add a new assignment
Controller:
public ActionResult Assignments()
{
var assignments = myContext.Assignments.OrderBy(x => x.DueDate);
return View(assignments);
}
[HttpPost]
public ActionResult AddAssignment(Assignment assignment)
{
myContext.Assignments.Add(assignment);
myContext.SaveChanges();
return RedirectToAction("Assignments");
}
// Returns a strongly-typed, partial view (type is Assignment)
public ActionResult AddAssignmentForm()
{
return PartialView();
}
Here's where I'm stuck: I want this form to have a drop down list for the different courses that an assignment could possibly belong to. For example, an assignment called "Chapter 3 Review, Questions 1-77" could belong to course "Pre-Algebra". However, if I use the code below, I have to explicitly declare the SelectListItems. I thought that with the given Assignment model above, I should be able to have the drop down list for Courses automatically generated using MVC awesomeness. What am I doing wrong?
AddAssignment Partial View:
#model MyModels.Assignment
#using(Html.BeginForm("AddAssignment", "Assignments"))
{
// Can't I create a drop down list without explicitly
// setting all of the SelectListItems?
#Html.DropDownListFor(x => x.Course, ....
}
Basically you are confusing/mixing your business model and your UI model.
The quick fix here is to add the data for the dropdown list to the ViewBag (a dynamic object).
Alternatively you could create a class AssignmentModel that contains the relevant Assignment properties and the List.
And No, this is not well supported in the templates.
You do realize you'll need some error handling in the Post method(s)?

Categories

Resources