What is the best ViewModel naming convention? [duplicate] - c#

This question already has answers here:
How do you name your ViewModel classes?
(6 answers)
Closed 6 years ago.
I'm writing an asp.net mvc2 project with a lot of views/partialviews. Reading on good MVC practices, I've been encourage to create ViewModels. Its really nice and makes sense to do so but I'm noticing recently that I can no longer easily remember what model is for what view. I'm hoping there is a nice naming convention for ViewModels that can handle large projects.
My question is can this situation be improved?

I like to keep it simple, for instance, if you have an object named Folder:
View = "FolderView.xaml"
ViewModel = "FolderViewModel.cs"

Make it simple:
ModelName = ViewName + "Model";
If you have model hierarchies, you sometimes need to pass the model from the view to partial views. In that case the above rule can be waived.

If you are keeping your view models in the same assembly as your views, one trick I have used to help organize views with view models in addition to a simple naming scheme like {View Name}ViewModel for the view model class is to do the following:
Create your view class (Shell.xaml)
In the same location, add your view
model class (ShellViewModel.cs)
Rename the view model class file to
be the same name as the view, but
append .model to the file path
(Shell.model.cs)
Edit the project file (either
manually or using the power command
extensions in VS)
Locate the Compile element for
the view model class in the project
XML document
Add a child DependentUpon element
whose content is the name of the
view class
Save changes and reload the project
This will cause the view model class to be visually grouped along side the code-behind file for the view.

For ASP.NET MVC I keep my view models in a ViewModels.{Controller} namespace and the class name is just {Action}. I don't use the ViewModel suffix just like how the view files don't have a View suffix.

I've started going one step further and specifying if a ViewModel is used to generate a Form via EditorFor by ending the name with Form. Helps keep forms vs. simple display models easily identifiable.

Related

MVC Core 2.0 HTML.Action vs Component.InvokeAsync

I am really struggling with changing my mindset from the #html.Action way of doing things to this new Component.Invoke way of life.
So to outline my structure. I have a Controller called "Contract" with the standard Index IActionResult.
In there I have a partial view that is a form, which I would have normally have just loaded from the index.cshtml using the following:
if(Something = my value){
#Html.Action("p_NewContract", new { id = x })
}
Which always worked.
For what I can read, I now need to make a new folder outside my nicely structured view and partial view folders under each Controller. The folder I HAVE to create is "Shared/Components/p_NewContract.cshtml"
And then in that folder, I need to create a .cs file with the postfix of ViewComponent (p_NewContractViewComponent.cs) And somehow the runtime will know those two things belong together?
In that CS file I then add [ViewComponent(Name = "p_NewContract")] before the public class and then after all that I can add to my Index.cshtml
#await Component.InvokeAsync("p_NewContract", new { id= 2})
I have done all of this, no sign of it working. Am I missing something fundamental, is there a way I can get my old Html.Action back? It was so much easier.
Any assistance to help my frustration would be great!
Caz
There's two parts to a view component: your class that derives from ViewComponent and a view that component should return. By convention, your view component classes actually go in /ViewComponents, while again by convention, your view goes into Views/Shared/Components/{component name}/Default.cshtml.
That's just convention, though. The same as how Razor automatically finds views based on controller/action name. In truth, the classes can go wherever you like. They are brought in via reflection, so as long as it's somewhere in the assembly or a referenced assembly, it will be found. The views likewise can be moved wherever you like, you just have to tell it where to find them, since it won't be able to do it automatically based on convention anymore. See: https://learn.microsoft.com/en-us/aspnet/core/mvc/views/view-components#view-search-path

Passing dynamic object to View

I decided to try avoid view models and pass dynamic data to views, here is the test code I wrote in my controller:
dynamic model = new ExpandoObject();
var user = unitOfWork.UserRepository.Get().First();
model.Title = "Dynamic test";
model.User = user;
return View(model);
And in View:
#Model.Title
#Model.User.UserName
I like this method more because I don't have to write ViewModel class for every controller action, and also don't have to change ViewModel every time I decide to pass a new property to View.
The only downside I see is lack of intellisense in Views, because they are not strongly typed any more, but that doesn't seem as a big problem.
My question is, is there any other downsides of using this approach instead of ViewModels, because I am just starting a new project in my company, and I don't want to regret later if I use this approach...
I believe that the main advantage of creating view models is readability and resuseability of the code.
If I go to your piece of controller which you pasted, technically I can understand it, but I don't know what the model is about from business perspective. Of course you can name it more descriptive, but I don't believe it resolve the issue.
Second thing is reuseability, so I can imagine a lot of situation when multiple views can use the same model or some part of models and in this case you need to copy & paste code which creates you dynamic model or create some helper function which do this for you.
Basically I believe that it will be very painful when those dynamic models need to be changed e.g you removed some property in controller, but you forgot to do the same in some of the views. You won't be informed by compilator that something is wrong.
Additionally without strongly typed view model I believe there is no way to create attribute based model validation (which is very common business case)

cshtml template + model passing

I've just joined half-finished project and I'm faily new to asp.net mvc.
I've noticed that the project has fair amount of controllers and also they're accompanied by even greater amount of views.
So the problem is many of these controllers extract data from the db and call a _*controllername*TableResult.cshtml view to render it (it's a partial view).
Now these views are very VERY similar and I find this code repeating somehow annoying (for creating new views). The problem I've found so far is that you have to pass the model
#model List<GroceriesTableModel>
There're some other differences like - ajax(actionName, controllerName) and id`s of the html - but all these can be fixed with a Dictionary?
My question: is there a way to somehow template these look alike views - and pass the correct model and a Dictionary object for the id`s?
Sure is - #Html.RenderPartial("_partialview", model, Dictionary)
search renderpartial for more details...

When is it "acceptable" to use ViewBag/ViewData in ASP.NET MVC?

I realize that the best practice is to use strongly typed Views and pass in all needed data in a ViewModel, but I am curious if there are situations where it is actually considered "best practice" to pass data in the ViewBag/ViewData.
In what scenarios is the ViewBag/ViewData preferred for passing data to a view?
update
It's great to hear the various uses everyone has come up with for ViewBag/ViewData. We may never arrive at a "best practice" but it will be great to see the different solutions people have come up with that rely on the ViewBag/ViewData.
I use them rarely, for bits of information that are totally unrelated to the model or view model that I'm passing to the view, again, most of the times I use a view model
I prefer to use some DTO instead of using viewbag. Using DTO make you strong type your viewdata.
Hope this helps.
I typically will use a strongly typed view for displaying any content but will often set ViewBag.Member to the currently logged in member so that it can be used in the main Layout in addition to the specific view.
I have an attribute called PopulateMemberContext which populates ViewBag.Member and I add that attribute to my base controller so that every view will always have the necessary data.
"Right" or "Wrong" I don't know - but it works wonderfully.
i can't say about best practice but i mostly use it when using Editor Templates. e.g if i want to display a dropdown list for editing certain field i make following editor template
<%:Html.DropDownList("GetIDHere", new SelectList((IEnumerable<someModel>)ViewData["xyz"]),"select Author")%>
Then you put UIHint attribute on BookID field of your model for instance
public class Book
{
public int BookID{get;set;}
[UIHint("mytemplate")]
public int AuthorID{get;set;}
}
in such cases, i assume, its particularly fine and clean to use ViewData. this is the way Telerik asp.net mvc projects have coded in their demo projects demo

ASP MVC2 model binding issue on POST with strongly-typed HTML helpers

So I'm looking at moving from MVC 1.0 to MVC 2.0 RTM. One of the conventions I'd like to start following is using the strongly-typed HTML helpers for generating controls like text boxes.
However, it looks like it won't be an easy jump. I tried migrating my first form, replacing lines like this:
<%= Html.TextBox("FirstName", Model.Data.FirstName, new {maxlength = 30}) %>
...for lines like this:
<%= Html.TextBoxFor(x => x.Data.FirstName, new {maxlength = 30}) %>
Previously, this would map into its appropriate view model on a POST, using the following method signature:
[HttpPost]
public ActionResult Registration(AccountViewInfo viewInfo)
Instead, it currently gets an empty object back. I believe the disconnect is in the fact that we pass the view model into a larger aggregate object that has some page metadata and other fun stuff along with it (hence x.Data.FirstName instead of x.FirstName).
So my question is: what is the best way to use the strongly-typed helpers while still allowing the MVC framework to appropriately cast the form collection to my view-model as it does in the original line? Is there any way to do it without changing the aggregate type we pass to the view?
Thanks!
UPDATE: So the bind attribute worked well, but I didn't love how I had to apply it to essentially every posted view model. I ended up changing the inheritance hierarchy such that all of our view models inherit from a base class that contains page content and other meta data, as opposed to being an aggregate property named Data.
public ActionResult Registration([Bind(Prefix = "data")] AccountViewInfo viewInfo);
This tells the binder that it should expect all values to start with data, so it will look for data.FirstName, etc.

Categories

Resources