I have a Models class ProjectDepo that defines 3 dozen properties. This has created a table in the db with those fields. I used Scaffolding to create the iCRUD Razor pages. All the fields are there correctly and are correctly populating the database table.
I want to create an iCRUD scaffold of only some of those fields/properties and filter the results. I would use a ViewModel choosing only those specific properties and querying to filter my results to base my scaffolding off of.
When I have created my ViewModel class, how do I specify which Model class these properties are from? Where can I add a SQL statement to filter the results?
I have searched but have not found the right terms. Everything is about binding the ViewModel to the View, I'm trying to get the data to the ViewModel.
Thank you for any assistance.
chuck
(This is my entire ViewModel class, abbreviated)
public class RequestReporterViewModel
{
//All fields are from ProjectDepo class
public int Id { get; set; }
public string OrderingPOCName { get; set; }...
}
(First, I received notification that someone did NOT like that I chose NOT to capitalize "sql"; that I used parenthesis, had extra spaces and listed the class in my question. ABSOLUTELY NONE of which made my question easier or more difficult to understand. The "suggested" and "approved" edits didn't help the question AT ALL. They didn't provide a solution, didn't make the question clearer - they ONLY made the question meet the suggesters format.)
(//end of rant)
Anyways, this question can be closed as I was looking for a way to handle this ViewModel WITHOUT creating a Controller.
I'll keep searching for an answer using different search criteria elsewhere.
thank you to anyone that took the time to read my question, it is appreciated.
chuck
if you want to map binded properties fron view to model you can use AutoMapper, AutoMapper is best practice for this state.
for your example :
Mapper.Map(RequestReporter, RequestReporterViewModel, typeof(RequestReporter), typeof(RequestReporterViewModel));
Related
I'm using entity framework. It auto generated an Answer class. But I cannot modify this class as it will be overwritten if code is regenerated.
Is there a way/technique to add data annotations using this class?
The reason I ask is that I have a Create Answer view that uses the Answer class. Hence, I want to add data annotations such as Required, etc.
If I cannot add data annotations to the Answer class, then I have to create an "AnswerDuplicate" class, pass that into the view, and also use that in my Create() method. However, I then have to map all the values from AnswerDuplicate to an instance of Answer, since Answer is what I "add" to the entity.
Seems like extra work since Answer is autocreated (class and the binding in Create() method). Would be nice if I can just add data annotations.
If this is not possible, then is my only option to create an "AnswerDuplicate" class and use that in place of the Answer class?
My suggestion is: Use ViewModels.
I always consider creating a ViewModel when editing/viewing data - rather than passing the model object directly down to the view.
How Will This Help?
The logic to display it in the view (with Required, DataType and validation such like) can be left down to the ViewModel; while your Model is just left as a normal all-intents-and-purposes class (in your case, a generated one).
As an example, you could have an AnswerViewModel, which contains all of your display/validation logic, to then use in your corresponding View.
How Do I Save Time Mapping Properties?
You can use AutoMapper (or other similar auto-mapping packages) to then automatically map the properties between your model and the view model, for easy updating of entities etc.
This then saves you time having to write lines-upon-lines of code to update entities - which may essentially need to change over time - this can be a big problem (and a huge PITA) if refactoring/adding extra properties across different classes.
How Does This Help Going Forward?
Well, because you are not leaving the logic up to your class:
Let's say you have 3 different views for different purposes (Add, Edit, Delete)
If (for some reason) you need to show/display something differently in only one particular view, you are able to just apply/change the logic in the relevant ViewModel; rather than worrying about updating the Model and having breaking changes affect everything else.
Here is a handy tutorial on How To Use ViewModels In MVC: http://rachelappel.com/use-viewmodels-to-manage-data-amp-organize-code-in-asp-net-mvc-applications/
I do hope this helps, somewhat :)
If you need me to provide any examples - just let me know.
I think the best solution is to use ViewModels as #Geoff James said, but if you don't like to add different classed you can write a partial class and add the MetadataType attribute to it and the add the attributes you want like Required to its properties.
public partial class Answer // this is auto-generated
{
public long AnswerID {set; get;}
}
[MetadataType(typeof(Answer ))]
public partial class Answer // this is what you can write
{
[Required]
public long AnswerID {set; get;}
}
remember that both class must have a same namespace.
And other solution to your problem is the you can switch to Code First
This question already has answers here:
POST a form array without successful
(5 answers)
Closed 7 years ago.
I'm starting with MVC and i have some basic questions that maybe you can orient me a little bit:
I'm Using MVC5 with Razor and EntityFramework 6. No AngularJS skills here.
I have a classic Master-Detail CRUD where i need to create Order and OrderItems. My idea es that when you create the order, you can add the items in the same form and then with one SAVE button create both records on the database (The Order and the Items).
I've created the "Orders" CRUD very good with scaffolding, and it works perfect. But now i need to add to the same VIEW the items, and here is what i'm getting lost and try different ways to do this:
BINDING ISSUE: I thought that probably i could add the list of OrderItems to the binding header on the CREATE event. My OrderController has this method:
public ActionResult Create([Bind(Include = "Id,Date,*other fields*")] Order order) and it works fine with the ORDER CRUD operations. But, now, if need to add a List to the list of fields binded on that header, is that possible? How should i save the data in the View then?
JSON: Another way i thought, was to remove the Binding header and use Json, but all the examples i've seen was using AngularJS and i have all the site done except for this CRUD, i preffer to let that option for the real last chance. On the other hand, i've found this: https://www.youtube.com/watch?v=ir9cMbNQP4w and it's exactly what i need to do, but: It's on MVC4 and not MVC5, and also i have all my entities validation in my model (extended) class and some of them in the controller as well (exclusively the ones related to the Creation or editing the order). Tell me if i'm wrong here please!
PARTIAL VIEW: The last way i've just tried was with Partial View. I've created succesfully the Initial data load based on this tutorial: http://dotnetmentors.com/mvc/render-partialview-with-model.aspx , but after that, i need to add new items to my order, or edit/delete the existing ones and here is where i get lost: Should i have different CREATE/EDIT methods for the partial views? How i send the data then? How i can use only one SAVE button that saves everything at the same time?
I'm getting more lost when i look for more information.... so, here i am asking for help to you guys !
Thanks a lot in advance !!
Create a custom view model:
public class NewOrderViewModel
{
public Order order { get; set; }
public OrderItem[] orderItems { get; set; }
}
Then you can use this in the view by changing #model NewOrderViewModel at the top and you will be able to use like:
#Html.TextBoxFor(m => m.order.Phone);
#Html.TextBoxFor(m => m.orderItems[0].ItemName);
You will need some javascript to copy the html and create new form elements for each new orderItem the user wants to add.
Then your controller signature would look like:
public ActionResult Create(NewOrderViewModel content)
From what I read, I understand that we should always pass a viewmodel to the view. However, sometimes this viewmodel is exactly or almost the same as the EF-model. Is it acceptable or is there any workaround to this problem (repetitive code) ?
For example, if I have this EF-Model :
class UserModel
{
string id {get;set}
string name {get;set}
string address {get;set}
string phone {get;set}
string website {get;set}
}
How should the viewmodel be ... like this :
class UserViewModel
{
string name {get;set}
string address {get;set}
string otherobject {get;set}
}
Or Like this :
class UserViewModel
{
UserModel user;
string otherobject {get;set}
}
With option #1, properties are repeated... and in another viewmodel they will be repeated again. And I will need to repeat all data annotations on each viewmodels. However, I send only the properties that I need.
With option #2, nothing is repeated, but I pass a lot of properties that I don't need.
The last option would be to mix option #1 and option #2 according to the needs... but I don't like this option because of the lack of a common standard. Sometimes the properties will be defined and datannoted in the viewmodels and sometimes in the EF-model.
I wish there is an option #4 that I don't see...?
Thank you.
The difference of those classes is how your application interacts with. Model and ViewModel has different audience.
Your Models should be interacting with your application, and sometimes many people prefer to use those models as entities in EF Code First. They are what we call Domain Objects.
On the other hand, ViewModels should be interacting with your Views. In your service layer, you populate your ViewModel with some data, and you can access them from your controllers.
However, sometimes this viewmodel is exactly or almost the same as the EF-model.
The keyword here is "sometimes". You are right, for a very simple application, you don't even need to think about ViewModels, where your models can simply be used in most cases. However, think about some cases for example where you want to display list of latest posts, latest comments, and let's say some related posts on a single view. What you are going to do? This is where the ViewModels come. You pass a specific ViewModel to your view, that contains all the necessary data, posts, comments, and related posts.
In most cases, you ViewModel should be build up from multiple Models, and sometimes, the porperties of a ViewModel are type of Models
I know it has been quite sometime since this question was asked. But, this may help someone who is looking for the answer.
Eventhough you have ViewModels which are almost same as models, it is recommended to create ViewModels with same code.
Possible reasons are
You may want to add validation to properties using Data Annotations.
It is not advised to have validation which are more specific to
screen in your models which are supposed to be reflections of your
DB structure.
Your ViewModels may change in future. It may not make sense now, but
there is always a possibility.
If you are worried about mapping code which looks obvious in most of the cases, you can make use of Automapper.
Cheers!
I'm hoping you guys can answer me a question?
I've only just started out using ASP.NET MVC3 have come unstuck at a certain point. I've been learning this stuff from books and I'm slightly unsure on a few things.
Can a VIEW, only have one #Model reference?
At the moment I have a VIEW setup with a HTTP-POST on a ViewResult, that validates the data in the View, entered by the user and then "on post", passes this info to a method that writes it back to a database(ADO.NET - Access). Now I need to change my VIEW, so that I can replace a couple of my text boxes for Dropdownlistfor controls. The Data to populate these controls will need to be passed in from the Database.
Would I be correct in saying that this data needs to be passed in the HTTP-GET Viewresult of the page, and if so, can i reference more than one #Model in this same View (*.cshtml).
I have a class that takes in the user response, and this is referenced in the View. But will i need to create a new class for the dropdownlist data and reference that too. So that in the background I populate the data into a SelectListItem, pass it to the View and then populate each drop down control within the view?
I'm sorry if this is poorly written, very hard to explain, I find learning from books hard and I'm pretty stuck now. Any help would be appreciated. Just to give me an understanding of how this all wraps around. I'm comfortable with the C# syntax, but very unsure of MVC3!
There are two ways you can handle this.
Use a View Model.
In this scenario you have a class that contains your data model as well as other things required by the view, so something like this:
public class ViewModel
{
public MyDomainModel Model { get; set; }
public IEnumerable<SelectListItem> SelectListItems { get; set; }
}
Use ViewBag.
In this case you add everything extra into the ViewBag dictionary. So in the controller, you'd have stuff like this:
ViewBag.SelectListItems = new SelectListItem[] { ... };
Then you can reference in the view itself
#Html.DropDownList("myselectlist", ViewBag.SelectListItems)
I think that this will help you pluralsight mvc3 intro. It sure helped me
I have just started working on an MVC project and things are going ok but it looks like I am creating alot of spaghetti code with just too many objects. Can anyone see how I can simplify this solution before the whole projects gets out of hand?
ok, here's my set up:
DAL - has Entity framework connections and methods to obtain data then convert the data to my model objects in the model layer
BLL - sends the data back up to the UI
Model - this contains all the model objects that are used throughout the site, anything coming from the DAL is converted into these objects by creating a new object then populating the variables.
UI - my MVC solution
The DAL,BLL and Model are also used by other solutions.
Now with MVC, I am trying to use the validation annotations ([Required], etc) which means I have to re-create the model objects with the annotations. This is fine but if I want to save the data back into the database I need to convert the classes which is just messy.
Can anyone see how I can use my current model class library with MVC model objects that use the validation annotations?
If I have not explained myself clearly please let me know and I will provide more details.
Thanks
Ideally there needs to be a separation from the domain models on one hand and MVC models (they are really ViewModels) on the other hand. This separation is really crucial and strongly advised.
These will look a lot similar in most cases although ViewModel can contain extra stuff. Then you can use AutoMapper to convert from one to the other.
For example:
public class User // in entity DLL
{
[Required]
public string Name {get; set;}
}
public class UserViewModel : User // in MVC DLL
{
public string LastVisitedPage {get; set;} // which only MVC needs to know
}
Mapper.Map<User, UserViewModel>();
Mapper.Map<UserViewModel, User>();
you can put the metadata in metadata objects without recreating the model objects. Here is a very simple way of doing it, however it does require that the model objects themselves are marked as partial. I hope that is OK if not this solution will not work for you.
[MetadataType(typeof(PreviousResultsMetaData))]
public partial class PreviousResults
{
public class PreviousResultsMetaData
{
[DisplayName("Class Ranking Score")]
[Required]
[Range(0.0, 100.0)]
public object ClassRankingScore { get; set; }
}
}
in the example above there is a data model object called PreviousResults that is created elsewhere by some scaffolding code. It defines the POCO object that is sent to and from database using LINQ. The MetadataType attribute indicates the class that will be used to hold the metadata. Then you simply create plain objects that match the names of your real data members and annotate them.
I hope this helps.
You can use FluentValidation framework for validation. Look here
http://fluentvalidation.codeplex.com/
You can perfectly add attributes to your BLL (the business entities). Just add a reference and add a using statement for System.ComponentModel.DataAnnotations. Apart from that, you can implement the IValidatableObject interface (which is pretty easy, see below).
For the mapping, you can use for example AutoMapper, so you don't have to write to much of mapping logic yourself (if you can take advantage of the name mapping magic).
Validate example:
ICollection<ValidationResult> validationErrors = new List<ValidationResult>();
var validationContext = new ValidationContext(this, null, null);
Validator.TryValidateObject(this, validationContext, ValidationErrors, true);
return validationErrors;