I have a bunch of tables. Each table has a "Status" column. The column has either the character A or I. A= Active and I= Inactive.
I have a create view corresponding to each table. I want to display a dropdownbox that shows two values- Active and Inactive and then map them accordingly.
I know I can do following in each view where I need the dropdown for status
#Html.DropDownListFor(model => model.status, new SelectList(new[] { new { ID = "A", Desc = "Active" }, new { ID = "I", Desc = "Inactive" } }, "ID", "Desc"))
however if tomorrow I decide to have add one more status i will have to change each and every view.
The other option is to create a dictionary and pass it through a view model sort of as explained in this article
however that means I have to create a viewmodel for each of my models just to accomodate the statuslist.
is there any other way I can achieve this?
I recommend using a View Model for each unique View. Long term it makes the UI easier to work with and maintain.
The View Model approach can be taken to an extreme and become counterproductive in my experience. For example, when creating a VM for a Customer Entity, I do not recreate a CustomerVM that has all the same properties of the Customer Entity. Instead, I just create a Customer Property on the CustomerVM that holds the entire Customer Entity. Some may disagree with this approach because I may be exposing more info to the View than it needs, if the view is not displaying all of the Customer Entity info. It's true, but I like solutions that are fast and easy to implement and maintain.
You never know what is going to be necessary in the future. Over time I have found this approach to be the most flexible solution.
So, then you could create a Base View Model for all views that have common look-up lists and have your new View Models inherit from this Base VM.
It's one way to do it. :)
Following link might be helpful for binding the dropdown list in mvc
http://www.c-sharpcorner.com/UploadFile/deveshomar/ways-to-bind-dropdown-list-in-Asp-Net-mvc/
Related
I'm using
ViewBag.Something = session.Query<Something>().ToList();
To pass information from class Something to View and use it in selectList
#Html.DropDownListFor(model => model.model, new
SelectList(ViewBag.Something, "Id", "name"), "--Smthing--")
Is that bad? and how can i change it to be better?
The practice is not at all bad but it is recommonded to have a List property in our mode it self. in your case something like
public ActinResult YourActionMethod()
{
YourModelObject.Something = session.Query<Something>().ToList();
// And return your view after further code statements
return View(YourModelObject);
}
Infact instead of the original list object you cancreate a SelectList object where you can easily bind key and value and send it to view. By this way you can add all your business and build your model at once place and can populate it from the location you want to. Later View will just use that model rather than applying some more intelligence to it. It helps alot as all your values resides under same object rather than some in Model and some in ViewBag.
Secondly this practice is also fine if you don't have this list at more than one place and you are not reusing this model in any views. Also if you want to access this property outside your view e.g. in Layout or in some parent view which is consuming your view.
You can take a look at following post which explains how to bind a list to your model.
Setting default selected value of selectlist inside an editor template
I prefer to add all my properties to the model of the view, but the ViewBag can be useful to add things that don't quite fit in the model. It can also be useful when binding to elements in the layout since it doesn't have access to the view's model.
Just a rookie in .NET MVC world and still learning
I created three EF models in framework, one is clients, one is order, and items, below is the relation:
Client Order Items
PK:ID PK Order.id PK Items.ID
... FK:Client.id ...
FK:Item.id
In this case I wanna display all the client information and the item details they've bought in one table, obviously I cannot use any DBcontext here. So what should I do to combine the three table's info and output that? Create a new model on those three?
Any ideas or article are very welcomed!
I would create a ViewModel with all of the Data that you want to display. This is the model that will get populated in the controller and then it would get passed to the View.
So in the View it would use the ViewModel and wouldn't need to know about the underlying Database Model.
And in the Controller you would get the data needed and populate the ViewModel and pass that model onto the View.
Here is a page with an examples. There are plenty more out there too. http://sampathloku.blogspot.com/2012/10/how-to-use-viewmodel-with-aspnet-mvc.html
Let me explain the whole context:
I'm using ASP.NET MVC 2, EF4 (POCO).
I trying to do a generic repository for my app.
I'm having problem on updating a many to many relationship.
I have an item that is related to other by a many to many table. In the View, the user picks the desired Categories, and send just the chosen id's to the Controller.
Then, the Controller queries the Category Repository, adding it to the main item:
item.Categories.Add(CategoriesRepository.Single(id);
But, when I go the Repository and try to save like this:
Entities.ApplyCurrentValues(entity);
Context.SaveChanges();
But, the state of my entity is Added.
Then, I Cannot save my entity :(.
How can I solve this problem?
Thanks for your answers.
I have in the View, the following code:
<%= Html.CheckBoxList("Categories", ((IEnumerable<Categories>)ViewData["Categories"]).ToDictionary(c => c.ID.ToString(), c => c.Name)
, Model.Categories.ToDictionary(c => c.ID.ToString(),c => c.Name )) %>
Where CheckBoxList is a HTMLHelper.
Im putting the ids as values in the View, because I dont know other way to put and then get this information from the View.
How can I use the ObjectStateManager.ChangeRelationshipState method?
Like this? :
itemRepository.Db.ObjectStateManager.ChangeRelationshipState(item, item.Categories, "Categories", System.Data.EntityState.Modified);
I trying in this way, but it returns error.
Help! lol
You've got a few problems.
1) ApplyCurrentValues only works for scalar-properties. Since your trying to add a Category to the Categories navigational property on Item, this will not work.
2) You say this:
the user picks the desired Categories, and send just the chosen id's to the Controller.
How can your Controller accept a bunch of id's? How is this model binding done? We need more info on how your View is bound to your model, what's being passed to the action method. But it sounds like you need to redesign this particular View with the help of a ViewModel.
3) Change tracking with POCO's in MVC is a royal pain in the butt. In your scenario, you'll need to use ObjectStateManager.ChangeRelationshipState to manually set the Categories relationship to **Modified.
Honesty though, it's more pain than it's worth. I went through this same problem.
Cop it on the chin - go grab the entity first and use Controller.UpdateModel:
[HttpPost]
public ActionResult Item(Item item)
{
// get the existing item
var existingItem = ItemRepository.Single(item.Id);
// use MVC to update the model, including navigational properties
UpdateModel(existingItem);
// save changes.
Context.SaveChanges();
}
I'm using NerdDinner as a guide for my first MVC/LINQ to SQL project. It discusses the use of the ViewModel pattern when a View needs data from multiple sources - in their example: Dinners and Countries (serves as the drop down list).
In my application, the problem is a bit different. It's not so much different data, rather data linked via a key constraint. I have a Story table that links to aspnet_users via the UserId key. I would like to have easy access to the UserName for each story.
Since I'm using the repository pattern and returning IQueryable in some cases for deferred execution, I'm struggling with the correct way to shape the data. So I'm using this VideModel pattern right now to make it work but not sure if it's the right way.
Instead of returing IQueryable Story (which wouldn't work since I need the UserName), I'm returning a new custom class UserStory, which has a Story property and a string Username property.
What are your thoughts?
It seems like your question has less to do with MVC as it is simply a question about how to access the story data based on the username string.
Would it be possible to create a view in your database with all the UserStory data, the username, along with userid in it? That way, you could select from the view based on the username you have.
To create the view, you would simply have to do a join between the user table and the userstory table based on the userid.
After that, you could still use the repository pattern with the IQueryable being returned.
If you are wanting to do updates, it would be simple to do since you still have the userid, and would be able to link back to the actual table which would need the update.
If you look at Kigg, you will see that they mess about with the initial model to create custom ViewModels. That's the thing that NerdDinner doesn't cover in any detail. You could create a StoriesWithUserName class that inherits from Stories, but adds a new property - UserName. Then you return that to your View which would inherit from IEnumerable<StoriesWithUserName>
[EDIT]
Oops. Didn't spot that you already did this :o)
Using the repository pattern and returning an IQueryable of Stories is fine. The relationship allows you to access the the username value something like this >>
Assuming you are returning the IQueryable in your model object:
foreach(Story story in Model.Stories)
{
// do something with the value
response.write(story.aspnet_user.UserName);
};
Your Repository method would look like this:
public List<Stories> GetStories(Guid UserId)
{
return datacontext.Stories.Where(u => u.UserId = UserId).ToList();
}
The relationship will automatically provide you with access to the UserName value in the foreach loop i first mentioned. nothing more is required.
I'm not sure why your pagination control failed on Count() though??
Hope this helps
And what do you put in your View?
A recent blog from Scott Hanselman about using a special model binder for easier testing led me to think about the following:
What do you put in your controller logic building the view model, and what should be put in the view? what he does is this:
var viewModel = new DinnerFormViewModel {
Dinner = dinner,
Countries = new SelectList(PhoneValidator.Countries, dinner.Country)
};
return View(viewModel);
Now, I use the same way of passing data to my view, but I am unsure about how he deals with the Countries property. You could argue both sides:
Wrapping the Countries list in the SelectList prepares the data for the view, much like you create a viewmodel DTO to pass your data.
On the other hand, it somehow feels like you're specifically manipulating the data to be used in a dropdown list, limiting the way the view deals with your data from the controller.
I feel this is a bit of a gray area on the separation of concerns between the view and the controller, and I can't really decide which way to go. Are there any best practices for this?
PS: To keep it simple, let's assume the default ASP.NET MVC context, so basically your out of the box project. Default view engine and all that jazz.
In MVC (at least this flavor of it), one of the controller's responsibilities is to prepare the data for the view. So I think it is perfectly acceptable to prepare a specific model for the views consumption that implies it will be used in a drop-down. In this case the controller is just making it easier for the view and in fact prevents awkward code from having to otherwise be trickling into the view. It also keeps one from having those magic strings in the ViewData like VieData["Countries"].
So to sum up, while it may seem that there is some gray area in terms of responsibilities, ultimately that is the job of the controller: to interact with the view and to transform the domain model into other models that are easier to consume by the view.
Some suggest that having one all-encompassing view model per view is ideal (dubbed Thunderdome Principle).