I am basically trying to display a dropdownlist on my data entry view, and the dropdownlist keeps giving me the error "An expression tree may not contain a dynamic operation". I have added "#Model MyModel" to the top of my view, but still can't get past this error. Does anyone have an idea of how to resolve this issue? I have a controller that looks like this
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
public class MyController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult EnterInfo()
{
GetUT myGetUT = new GetUT();
ViewBag.uts = GetOptions();
return View(myGetUT);
}
[HttpPost]
public ActionResult EnterInfo(GetUT myGetUT)
{
ViewBag.uts = GetOptions();
return View(myGetUT);
}
private List<UT> GetOptions()
{
List<UT> uts = new List<UT>();
uts.Add(new UT() { ID = 1, Name = "1st" });
uts.Add(new UT() { ID = 2, Name = "2nd" });
uts.Add(new UT() { ID = 3, Name = "3rd" });
uts.Add(new UT() { ID = 4, Name = "4th" });
return uts;
}
}
}
and a view that looks like
#Model MyModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>EnterInfo</title>
</head>
<body>
<div>
#Html.DropDownListFor(x => x.UTID, new SelectList(ViewBag.uts, "ID", "Name", Model.UTID))
Enter an Amount :-<input type="text" name="Amount" /><br />
<input type="submit" value="Submit Info" />
</div>
</body>
</html>
Thanks for all the help.
Well, ViewBag is a dynamic type, so I assume that is what it is complaining about. Try putting public List<UT> UTs { get; set; } as a property on MyModel and change your helper to use the UTs property from your model. Like this:
Controller:
public ActionResult EnterInfo()
{
GetUT myGetUT = new GetUT();
myGetUT.UTs = GetOptions();
return View(myGetUT);
}
View:
#Html.DropDownListFor(x => x.UTID,
new SelectList(Model.UTs, "ID", "Name", Model.UTID))`
Edit: If it isn't obvious, your view should be typed to a GetUT type (because that's what you are passing in to the View() function in the EnterInfo action) - I assume that's what you mean when you said #Model MyModel. If not, change it to #Model GetUT and put the property on the GetUT class.
Related
When my page loads in "edit" mode, my text fields render correctly, but my numeric fields render with the error validation text visible, even though the value in the field is valid:
My problem is in a more complex project, but I was able to reproduce it in an out-of-the-box MVC 3 application in which I just added these bits. Why does the numeric field display the error text but the text field is fine when the page loads?
What is going on here?
I have the following for my Model, Controller, and View:
Model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace MvcIssues.Models
{
public enum Operations
{
View = 0,
Edit = 1
}
public class ShowsModel
{
public Operations Operation { get; set; }
[Display(Name = "Name")]
[DataType(DataType.Text)]
[StringLength(10)]
public string Name { get; set; }
[Display(Name = "Number")]
[Required]
[Range(typeof(int), "1", "999")]
public int Number { get; set; }
}
}
Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcIssues.Models;
using MvcIssues.Data;
namespace MvcIssues.Controllers
{
public class TestController : Controller
{
// GET: /Test/Shows
[AcceptVerbs(HttpVerbs.Get)]
[ActionName("Shows")]
[Authorize]
public ActionResult SelectedShows()
{
ShowsData shows = MvcApplication.Shows;
ShowsModel model = new ShowsModel();
model.Operation = Operations.View;
model.Name = shows.Name;
model.Number = shows.Number;
return View(model);
}
// POST: /Test/Shows
[AcceptVerbs(HttpVerbs.Post)]
[ActionName("Shows")]
[ValidateInput(false)]
[Authorize]
public ActionResult ShowsSubmit(ShowsModel data)
{
string name = data.Name;
int number = data.Number;
ShowsModel model = new ShowsModel();
if (Request.Form.AllKeys.Contains("btnEdit"))
{
ShowsData shows = MvcApplication.Shows;
model.Name = shows.Name;
model.Number = shows.Number;
model.Operation = Operations.Edit;
}
else if (Request.Form.AllKeys.Contains("btnCancel"))
{
ShowsData shows = MvcApplication.Shows;
model.Name = shows.Name;
model.Number = shows.Number;
model.Operation = Operations.View;
}
else if (Request.Form.AllKeys.Contains("btnSaveEdit"))
{
ShowsData shows = MvcApplication.Shows;
shows.Name = name;
shows.Number = number;
model.Name = shows.Name;
model.Number = shows.Number;
model.Operation = Operations.View;
}
return View("Shows", model);
}
}
}
View:
#model MvcIssues.Models.ShowsModel
<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>
<h2>Test Page</h2>
<div>
Show = #this.ViewData.Model.Name
<br />
Number = #this.ViewData.Model.Number.ToString()
</div>
<hr />
<div>
#Html.ValidationSummary(true, "oops!")
#using (Html.BeginForm())
{
<div>
Name: #(this.ViewData.Model.Operation == MvcIssues.Models.Operations.View ?
Html.TextBoxFor(m => m.Name, new { disabled = "disabled", maxLength = "20" })
:
Html.TextBoxFor(m => m.Name))
#Html.ValidationMessageFor(m => m.Name)
<br />
Number: #(this.ViewData.Model.Operation == MvcIssues.Models.Operations.View ?
Html.TextBoxFor(m => m.Number, new { disabled = "disabled" })
:
Html.TextBoxFor(m => m.Number))
#Html.ValidationMessageFor(m => m.Number)
</div>
<div>
#switch (this.ViewData.Model.Operation)
{
case MvcIssues.Models.Operations.Edit:
<input type="submit" name="btnSaveEdit" value="Save" />
<input type="submit" name="btnCancel" value="Cancel" />
break;
case MvcIssues.Models.Operations.View:
default:
<input type="submit" name="btnEdit" value="Edit" />
break;
}
</div>
}
</div>
If anyone can help me it would be much appreciated.
I had the same problem too. Here's what caused it, and how I fixed it:
The cause:
[Authorize]
[HttpGet]
public ActionResult BidToolv2(BidToolv2ViewModel model)
{
...
The fix:
[Authorize]
[HttpGet]
public ActionResult BidToolv2()
{
BidToolv2ViewModel model = new BidToolv2ViewModel();
Essentially the problem was when the user first visited the page, the controller took an empty model and when the page loaded, it assumed it had already been passed the model (perhaps?). Not totally sure on that, but to fix it I removed the model as a parameter and instead created a model in the controller action itself
Hope this helps!
Okay, posted this to asp.net forum. Probably a little bit more concisely worded version of the same question.
Solution was a bit of a hack but seems to be working well - created empty constructors for my problematic view model classes and inside the empty constructors I initialized the properties to valid values. Did the trick.
You need Required to make sure something is entered.
You need Range to make sure when something is entered that the values meet your requirements
Example:
[Required(ErrorMessage="Weekly Rental value is required")]
[Range(1, 9999, ErrorMessage = "Value must be between 1 - 9,999")]
public string WeeklyRental { get; set; }
I have a class and create an instance and fill a property in my index but when I push the submit button in my view and return again to my index action the property of my class is null.
How can I save the data when I return to my action and retrieve it? Is it possible?
I used viewbag and viewdata in my index and fill theme but when returned to index action again all of theme were null :(
public class myclass
{
public string tp { get; set; }
}
public class HomeController : Controller
{
//
// GET: /Home/
myclass myc = new myclass();
public ActionResult Index()
{
myc.tp = "abc";
return View(myc);
}
}
View:
#model MvcApplication2.Controllers.myclass
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>Index</title>
</head>
<body>
#using (Html.BeginForm())
{
<input id="Submit1" type="submit" value="submit" />
}
</body>
</html>
simply use either GET or POST method in your Controller according to your form method like,
[HttpGet]
public ActionResult Index(string id)
{
myc.tp = id;
return View(myc);
}
In your HttpPost you can get the model and see it's properties if you provided input fields for the properties in your view.
[HttpPost]
public ActionResult Index(myclass myc)
{
//check the myc properties here
return View(myc);
}
Then in your View:
#using (Html.BeginForm())
{
#Html.TextBoxFor(m => m.tp)
I have the below code in my VIEW, and thereafter a submit button. I do have many of these checkboxes in my view, so that the user can click on as many as he wishes.
#Html.CheckBox("code" + l_code, false, new { Value = #item.expertiseCode })
In my controller i have the fll., which is the HTTPPost method
public ActionResult RegisterSP(RegisterModel model, FormCollection collection)
However, when debugging, i see that ALL the checkboxes are being passed back to the controller, and not just the ones that were clicked on. I just want the ones that were clicked on and ignore the rest for i need to add these to the DB. Also, the checbox values passed in contains TRUE/FALSE. Because of this the false value is also being added to the DB. If i use the below method (not using the htmlHelper), i dont have the above problem. But i wud like to use the htmlHelper:
<input type="checkbox" name="code#(l_code)" value="#item.expertiseCode" />
IF you have a collection of Checkboxes, Create a ViewModel like this
public class ExpertiseCodeViewModel
{
public string Name { set;get;}
public int ExpertiseId { set;get;}
public bool IsSelected { set;get;}
}
Now In your main ViewModel, Add a collection of this as a property
public class UserViewModel
{
public List<ExpertiseCodeViewModel > Expertises{ set; get; }
public UserViewModel()
{
if(this.Expertises==null)
this.Expertises=new List<ExpertiseCodeViewModel>();
}
}
And in your create an editor template called ExpertiseCodeViewModel
#model ExpertiseCodeViewModel
#Html.CheckBoxFor(x => x.IsSelected)
#Html.LabelFor(x => x.IsSelected, Model.Name)
#Html.HiddenFor(x => x.ExpertiseId )
Include this in your Main View
#model UserViewModel
#using (Html.BeginForm())
{
//other elements
#Html.EditorFor(m=>m.Expertises)
<input type="submit" value="Save" />
}
In your HTTPPost Action method,
[HttpPost]
public ActionResult Save(UserViewModel model)
{
List<int> items=new List<int>();
foreach (ExpertiseCodeViewModel objItem in model.Expertises)
{
if (objPVM.IsSelected)
{
//you can get the selected item id here
items.Add(objItem.ExpertiseId);
}
}
}
Try
#Html.CheckBox("code" + l_code, false, new { #value = item.expertiseCode })
or
string name = "code" + l_code;
#Html.CheckBox(name, false, new { #value = item.expertiseCode })
I'm sure this is easy, but maybe I haven't searched well ...
I want to know how to get results from a partial view back to the model and/or controller.
If the user enters a FirstName, Gender (from drop down) and Grade (from drop down), I only find then FirstName and Gender in the model. I want to know how to get the Grade from the drop down in the partial view all the way back into the model, so I can see it in the controller.
Please look for this question in the controller code:
What do I need to do to get the GradeLevel from the partial class to be here: <<<<<
Note: this is not the exact code. There may be small, insignificant typo's.
EDIT: Apparently you can't add a long comment, so I will add here:
Thank you, Tom and Mystere Man. Tom got me thinking as to why it doesn't work. I didn't think through the model binding. With the design I proposed, the HTML gets rendered and the Grade drop down has this id: "Grade". The property on the model I want to bind to is: "GradeLevelID". If I change the helper in the partial view to be #Html.DropDownList("GradeLevelID" ... it works perfectly.
But that is not a good solution. My idea was to abstract the partial view from the main view. Hard coding the name blows that! I did work up a slightly improved solution. In the main view, I change the #Html.Partial statement to pass the model property name to the partial. Like such:
#Html.Partial("GradeDropDown", (SelectList)Model.GradeSelectList, new ViewDataDictionary { { "modelPropertyName", "GradeLevelID" } })
Then I could change the partial view to say
#model System.Web.Mvc.SelectList
#Html.DropDownList((string)ViewData["modelPropertyName"], Model)
But that also seems like a goofy way to approach things. Thanks for the help. I'll look at EditorTemplates.
Here is my model:
public class RegisterModel{
public MemberRegistration MemberRegistration{
get{
if (HttpContext.Current.Session["MemberRegistration"] == null){
return null;
}
return (MemberRegistration)HttpContext.Current.Session["MemberRegistration"];
}
set{
HttpContext.Current.Session["MemberRegistration"] = value;
}
}
public string FirstName{
get{
return MemberRegistration.FirstName;
}
set{
MemberRegistration.FirstName = value;
}
}
public SelectList GenderSelectList{
get{
List<object> tempList = new List<object>();
tempList.Add(new { Value = "", Text = "" });
tempList.Add(new { Value = "M", Text = "Male" });
tempList.Add(new { Value = "F", Text = "Female" });
return new SelectList(tempList, "value", "text", MemberRegistration.Gender);
}
}
[Required(ErrorMessage = "Gender is required")]
public string Gender{
get{
return MemberRegistration.MemberPerson.Gender;
}
set{
MemberRegistration.MemberPerson.Gender = value;
}
}
public SelectList GradeLevelSelectList{
get{
List<object> tempList = new List<object>();
tempList.Add(new { Value = "", Text = "" });
tempList.Add(new { Value = "1", Text = "1st" });
tempList.Add(new { Value = "2", Text = "2nd" });
tempList.Add(new { Value = "3", Text = "3rd" });
tempList.Add(new { Value = "4", Text = "4th" });
return new SelectList(tempList, "value", "text", MemberRegistration.GradeLevel);
}
}
[Required(ErrorMessage = "Grade is required")]
public Int32 GradeLevel{
get{
return MemberRegistration.GradeLevel;
}
set{
MemberRegistration.GradeLevel = value;
}
}
}
Here is my main view:
#model RegisterModel
#using (Html.BeginForm())
{
<p class="DataPrompt">
<span class="BasicLabel">First Name:</span>
<br />
#Html.EditorFor(x => x.FirstName)
</p>
<p class="DataPrompt">
<span class="BasicLabel">Gender:</span>
<br />
#Html.DropDownListFor(x => x.Gender, Model.GenderSelectList)
</p>
<p class="DataPrompt">
<span class="BasicLabel">Grade:</span><span class="Required">*</span>
<br />
#Html.Partial("GradeDropDown", (SelectList)Model.GradeLevelSelectList)
</p>
<p class="DataPrompt">
<input type="submit" name="button" value="Next" />
</p>
}
Here is my partial view (named "GradeDropDown"):
#model System.Web.Mvc.SelectList
#Html.DropDownList("Grade", Model)
Here is my controller:
[HttpPost]
public ActionResult PlayerInfo(RegisterModel model)
{
string FirstName = model.Registration.FirstName;
string Gender = model.Registration.Gender;
>>>>> What do I need to do to get the GradeLevel from the partial class to be here: <<<<<
Int32 GradeLevel = model.Registration.GradeLevel;
return RedirectToAction("Waivers");
}
I don't even know why you are using a partial view. All you're doing is using one helper method, you could replace the partial view with the helper method in the view and it would be less code.
Second, you should be using Html.DropDownListFor() instead of Html.DropDownList(), then it will correctly name the html controls for you.
Just do this:
<p class="DataPrompt">
<span class="BasicLabel">Grade:</span><span class="Required">*</span>
<br />
#Html.DropDownListFor(m => m.GradeLevel, (SelectList)Model.GradeLevelSelectList)
</p>
try this to get the correct naming for the elements when they get posted.
On your main view
#Html.Partial("GradeDropDown", Model) //Pass the Model to the partial view
Here is your partial view (named "GradeDropDown"):
#model RegisterModel
#Html.DropDownList("Grade", (SelectList)Model.GradeLevelSelectList)
this is my Model1 class
namespace chetan.Models
{
public class Model1
{
public string selectedItem { get; set; }
public IEnumerable<SelectListItem> items { get; set; }
}
}
this is my controller class
public class HomeController : Controller
{
private rikuEntities rk = new rikuEntities();
public ActionResult Index()
{
var model = new Model1
{
items = new[]
{
new SelectListItem { Value = "Theory", Text = "Theory" },
new SelectListItem { Value = "Appliance", Text = "Appliance" },
new SelectListItem { Value = "Lab", Text = "Lab" }
}
}; return View(model);
}
public ActionResult viewToController(Model1 m)
{
string getSelectedName = m.selectedItem;
return Content(getSelectedName);
}
}
this is my view...
#using (Html.BeginForm("viewToController", "Home"))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>emp</legend>
<div class="editor-field">
#Html.DropDownListFor(x => x.selectedItem,
new SelectList(Model.items, "Value", "Text"))
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
i want to add a drop downlist and i want to use selected value in viewToController action of homeController. and there is also one error in View page is "an expression tree may not contain dynamic operation" in (x=>x.selectedItem). Please solve my problem .
I don't understnad what you exactly need. You want to dynamicly add items to the drop down from the database?
I'm big fan of jQuery. You can do everything what you want with HTML using jQuery. So if you are looking how to automaticly add items to the drop down, take look at this: How do I add options to a DropDownList using jQuery?