I have an MVC3 C#.Net web site and I have a lookup table "Methods" in SQL server. I want to create a drop down list that populates the list of values from the "Name" column in my "Methods" table. I have an object, "Task", that has a string property "MethodName". I want to attach the selected value from the Drop Down list to this property in the Task object. How do I do this?
Make a model that contains a task and a list of methods. Get all the methods and the task you want from db in your "custom" model. Pass the model into your view
Set in your view in the top #model NameProject.Folder.Modelname
Then add to your view:
List<SelectListItem> items = new List< SelectListItem>();
Foreach(var m in Model.Methods) {
items.Add(new SelectListItem{Value=#m.Id.toString() , Text=#m.MethodName})
}
Then you could use html helpers that can help you bind model
#Html.DropDownListFor(model => Model.Task.Method, items)
In your controller that gets the post request use your model with task and methods as a parameter then just validate and savechanges
Related
I am using Entity Framework code first with a generic repository pattern with ASP.NET MVC. I have two tables Category and Product.
My model class of product is like this
Public class Product
{
public int ProductID{get;set;}
Public int CategoryID{get;set;}
[ForeignKey("CategoryID")]
public virtual Category Category{get;set;}
[NotMapped]
public string CategoryName{get;set;}
}
The model is binding correctly as long as I am getting data using DBContext.
But I am having a problem when I am getting list of products from stored procedure mapped to Product object. So it is not mapping the Category property of Product object and hence I cannot able to get Category.CategoryName.
So I added a new property with [NotMapped] attribute in product class as CategoryName. But it is also not binding from stored procedure.
And if I remove the [NotMapped] attribute then it is correctly binding from stored procedure but error occurs again when getting product by DbContext (Linq).
Please help me in this regards.
You don't need to add an extra property, use the DbSet.SqlQuery method for queries that return entity types. The returned objects must be of the type expected by the DbSet object, and they are automatically tracked by the database context unless you turn tracking off.
var products= _context.Products.SqlQuery("storedProcedureName",params);
The columns returned by SP should match the properties of your entity type otherwise, it will throw an exception.
After execute your SP, you should be able of get the CategoryName through your Category navigation property:
var catName=someProduct.Category.CategoryName;
On the other hand, the returned data by the Database.SqlQuery isn't tracked by the database context, even if you use this method to retrieve entity types. If you want to track the entities that you get after execute your SP using this method, you can try this:
//Attach the entity to the DbContext
_context.Product.Attach(someProduct);
//The Category navigation property will be lazy loaded
var catName=someProduct.Category.CategoryName;
If you have disabled lazy loading you can load explicitly your navigation property:
//Load the Category navigation property explicitly
_context.Entry(someProduct).Reference(c => c.Category).Load();
I am using mvc 3 razor and problem is recording the dropdownlist value in database using razor helpers:
#Html.DropDownListFor(m => m.Question, (IEnumerable<SelectListItem>)ViewBag.QuestionList)
Here, My view is using model binding. while in database the question column is of sting data type (varchar) and while running application it shows following erros after submitting form
The ViewData item that has the key 'Question' is of type 'System.String' but must be of type 'IEnumerable<SelectListItem>'.
What should I change here to avoid erros here I have to use model binding.
What should I change here to avoid erros here I have to use model binding.
You should ensure that inside the controller action that rendered this view you have populated the ViewBag.QuestionList property with an IEnumerable<SelectListItem>. People usually forget to do this in their POST actions when redisplaying the same view containing this DropDown:
IEnumerable<SelectListItem> items = ...
ViewBag.QuestionList = items;
return View(someModel);
Also make sure that the Question property on your model is a scalar type (string, integer, ...) and not a complex type. If it is a complex type you need to select the corresponding scalar property to bind the selected value to:
#Html.DropDownListFor(
m => m.Question.QuestionId,
(IEnumerable<SelectListItem>)ViewBag.QuestionList
)
I have a register model thats tighly bound to a register view. The register model has a selectlistitem poperty. Im having trouble populating a dropdownbox with the select list items.
var users = Roles.GetAllRoles();
model.UserRoles = users.Select(m => new SelectListItem()
{Value = m.ToString(),Text = m.ToString()})
#Html.DropDownListFor(r=>r.ToString(),Model.UserRoles,"Select Role")
You need to bind the selected value to a property of your model, like so:
(in your Model):
public string ActiveRole { get; set; }
...
(in your View):
#Html.DropDownListFor(m => m.ActiveRole, Model.UserRoles,"Select Role")
The first argument of the DropDownListFor method is the property which holds the value of the list. If the value in the list will be the id of the role this has to have the argument x => x.RoleId where x is your model and RoleId is the property in the model. You are binding the dropdownlist to the string representation of the viewmodel, the result of which is garbage.
The second argument is an IEnumerable<SelectListItem> which holds the options for the list. This object has the following values: Value is the value that is send back to the server, this should be what identifies the role, often the id of the role. Text is the text that is displayed in the list, it is what the user sees. Selected is a boolean that indicates which item in the list is selected. If it is false in all of the SelectListItems, the top one is selected, which is standard HTML behaviour.
In your case, you are placing the SelectListItems in the model, which is an unnecessary step, but should work. The model binder won't understand the first argument though, so you need to fix that one.
You can create a dropdownlist using
#Html.DropDownListFor(model => model.SelectedId, model.DropDownItems);
but where does DropDownListFor get the value to pass into the model => model.SelectedId lambda from?
SelectedId is just the integer of the field in the model.
the model is passed in from the controller using
return View(myModel);
And the model can be defined in the view at the top
#model mymodelnamespace.RoomBookingInsert
So the dropdownbox's value is set as the SelectedId field in your model.
A proper field name for example would be RoomNo if that clarifies it better.
#Html.DropDownListFor(model => model.RoomNo, model.Rooms);
As long as model.DropDownItems (or model.Rooms in my example) Contains a item with the value of that attribute, it will set it as the selected item in the list as default.
Edit:
If you are using viewbag, rather than the model, instead use DropDownList. (each input has a for extension for use with models)
#Html.DropDownList("RoomNo",
new SelectList(ViewBag.Rooms as System.Collections.IEnumerable ?? Enumerable.Empty<SelectListItem>(), "RoomNo", "RoomName"),
new { #value = #ViewBag.RoomNo})
This above, creates an input form with id RoomNo,
and uses a SelectList that will default to empty if null. The fields that defined the values and text shown are set at the end of the select list parameters.
The last bit sets the default value to the contents of #ViewBag.RoomNo.
You can also create the select list in the controller, and then simply set the dropdown options to the viewbag.myselectList entity.
I have a SQL database with has the following: Customer, Item, Clothing and Food.
Item holds a key to Clothing or Food.
Item also holds a key to Customer. Therefore a customer can have an item, which may be of food or clothing.
I am using ADO.Net Entity Framework and have this generated automatically.
I currently have the following set-up: A person may enter their ID on the webpage and this is sent via a form post where the controller picks it up and queries the database using LINQ to get the customer. The customer view (details) is then returned. I can now see all the customer details etc.
However, what I want is to be able to see the items the customer has, the different food items and clothing items, but I am unsure how to do this. I also want to be able to allow the user to edit one field of the clothes and food items tables. Any idea how I would implement this?
Here is an ActionResult in my CustomerController:
public ActionResult Details(int id)
{
var cust = (from c in dataModel.Customers
where (c.MembershipID == id)
select c).First();
return View(cust);
}
I can also write cust.Items which is the entity which I want to display in the view with the customer (their items). How would I display this in the view also?
Hopefully this makes it a little more clear on what I am trying to achieve and how.
Thanks.
Using Entity Framework, if you're tables are linked properly with the right foreign keys and all that then your Customer entity should have a property that is a collection of Items.
You could also create your own strongly typed ViewModel that has a field for Customer and implement your own properties for Clothing and Food and populate those with another query.
This question was asked last night but its similar. The guy in the question wanted information to populate a dropdown passed in. You want something similar, not for a dropdown, but to fill in textboxes to edit. How to properly populate drop downs from ViewData in controller on multiple views in ASP.NET MVC
To create a ViewModel start by creating a new class and name it CustomerAndItemsViewModel, for example.
public class CustomerAndItemsViewModel
{
public Customer Customer { get; set; }
public IQueryable<Items> Items { get; set; }
}
public ActionResult Details(int id)
{
var cust = (from c in dataModel.Customers
where (c.MembershipID == id)
select c).First();
var items = (from i in dataModel.Items
where (i.MembershipID == cust.MembershipID)
select i;
return View(new CustomerAndItemsViewModel { Customer = cust, Items = items });
}
And don't forget that you will no longer be passing a Customer to your view. So you need to change the line at the top to something like:
#model Your.Path.To.CustomerAndItemsViewModel
Typically, if you want to pass back information that is not contained in just one of your entities, you have to create a class that encompasses more than one object. So, if you want a page that displays your customer information, and all their items (which they can then edit), you would need to have a the controller action pass back a "CustomerAndItems" object (or something similarly named). This object would hold a reference to the Customer as well as a collection of their Items. (You build the CustomerAndItems object within your Action.)
Then, your view would be strongly typed to CustomerAndItems, and you can then display each piece of information as you normally would.