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)
Related
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));
So I'm consuming a RESTFul API to get the data I need. This API returns json and i converted this to C# models. The API returns some general info about a vendor and an array with products. The array of products also consists out of arrays for pricing information and product availability etc...
The problem im facing is that when a product is selected by a user to buy i have to gather specific information out of the different array's. Currently I've made a ViewModel for the data that needs to be send to process the order. This is done by binding the actual data using hidden fields and use a HttpPost from the view, resulting in +/- 30 hidden fields to set the proper data values.
I'm kinda new to MVC and this seems dirty. I thought i would be able to pass the models(for example the VendorModel,ProductModel,PricingModel,AvailabilityModel) from the view(with a POST) to the controller and create the ViewModel(based on the models send) so that i can send that to the API.
Is this actually how it should be done or is my design faulty and should i approach this differently?
A side note: One of the things i found is that most people suggest to use an identifier to get the data you need but the problem is that the API doesn't have the right calls to get Product, Pricing, Availability data based on Id, its just one big object with array's based on the search query.
Edit
So after some information i decided to try out nested models and created a viewmodel like this:
public class TestViewModel
{
public TestViewModel()
{
productInfo = new ProductInfo();
}
public ProductInfo productInfo { get; set; }
}
My view is like this(super simpel):
#using (Html.BeginForm("CreateOrder","Products"))
{
//Vender info etc...
//This is how i render partial view now:
{Html.RenderPartial("Info/ProductInfo", Product.ProductInformation.ProductInfo);}
<input type="submit" value="Order" class="btn btn-default" />
}
My controller(TestViewModel.ProductInfo is always null):
public ActionResult MakeReservation(TestViewModel testViewModel)
{
//Doesnt do anything just debugging TestViewModel
return View();
}
I'm not posting any inputs but just want to pass the modal with the data to the controller. How will MVC know which data to bind, because now it doesnt bind. Do i have to bind it myself somehow?
I had the similar situation and I have one suggestion, you can pass all the models to the view as save in a javascript object as JSON using the example code which I used like below-
<script type="text/javascript">
var pageBlockOptionsJSON = #(Html.Raw(Json.Encode(DesignOrderBlocks)));
var controlTypeJSON = #(Html.Raw(Json.Encode(controlList)));
</script>
Then you can do all the manipulations using jQuery to structure and create a javascript object and post that object to Controller Action. You can create the same or exact structure which is needed on the server. As specified in this url - http://www.nickriggs.com/posts/post-complex-javascript-objects-to-asp-net-mvc-controllers/
In this way you don't need to have use huge amount of hidden fields and you can do all the dirty work on the client side using jQuery.
I am sure this will help you out in doing the thing in the right way. Let me know if you need some details.
For people that somehow find this questions i solved this issue by saving the model to an database as an search result using entity framework. After getting the result i save it and create a viewmodel. After posting i send the id's that entity framework generated and search the right models in the database creating a new postviewmodel.
This question already has an answer here:
Posting to a list<modeltype> MVC3
(1 answer)
Closed 12 months ago.
I am creating a wizard and I need to propagate a list that I have created. The list is of my Contact model. I need to put this in the form so that when I post back to the controller on my final step I can have the list of Contacts as part of the wizard model (it just returns null now). For other simple form objects I use a HiddenFor to keep the data in the model. This doesn't work because a hidden for is just a text box and I have a complex object.
I considered creating a DropDownListFor and wrapping it in a hidden div. This is just patchwork and would actually take a bit of work to get DropDownListFor to accept another object type (if it would work at all).
I have considered saving the list to Session["Contacts"], but that does not seem like the proper MVC way to go. Does anyone have any better suggestions?
Thanks,
TJ
--UPDATE--
In response to merekel I am adding more detail to clarify where I am having the issue. This list is not modified by the user and will not display on the form. I create the list in one of my wizard steps and save it to my model like this.
View Model
public class WizardViewModel
{
//...
public List<Contact> ContactList { get; set; }
//...
}
Controller code
//Step 4 in the wizard
model.ContactList = CALL FUNCTION THAT CREATES LIST BASED ON FORM SELECTIONS
//other calculations needed for step 5
//Save Contacts for later
Session["Contacts"] = model.ContactList;
//Step 5 in the wizard
//Readd the contacts to the model
model.ContactList = (List<Contact>)Session["Contacts"];
//Save the model to pass to the report page
//My report viewer is on an ASPX page so I am passing all the data here with a session
Session["ReportModel"] = model;
The session save works as expected. It just does not seem like I should be using sessions to save data from page to page with MVC. I need to when going from MVC to ASPX, so I am not worried about Session["ReportModel"] only Session["Contacts"]. Thank you for any suggestions.
I believe that posts like this will help 1, 2. There are many posts similar to these on how to post back lists.
Are these contacts populated from your form or are they global contacts?
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 one class like
public class Questions
{
public long ID { get; set; }
public string questionText { get; set; }
public int questionType { get; set; }
}
Now when various questions are created in the view and submitted, what should be the controller's action code and how should I design my view so that I can get the list of questions with all the properties set directly?
Thanks in advance.
Model binding to IList<T>
I've written about model binding to IList<T>. I think this is exactly the problem that you're trying to solve. And there are some more posts on my blog that may help you lots especially because you didn't say whether you're having an HTML form of questions or Javascript objects built by some generic question form. Anyway. These two posts will help you address both problems:
Asp.net MVC model binding to IList<T>
Sending complex JSON objects to Asp.net MVC using jQuery Ajax
By understanding Asp.net MVC model binding you will be able to easily bind your client-side data (forms or objects) to:
public ActionResult AddQuestions(IList<Question> questions)
{
// process questions
}
Suppose you're posting back an HTML form
The main requirement is that you index your HTML field names correctly, because names are those that get posted back to server. In your case your fields should be:
<input type="text" value="questions[0].questionText" />
<select name="question[0].questionType">
<!-- options -->
</select>
When you dynamically add new pairs (to form new questions) you have to make sure:
item indexing starts with 0 and
there are no gaps in indexes.
If you also provide the ability to remove certain questions (while adding/editing them), you will have to reindex items on each removal.
Model validation (forms or correctly prepared objects)
The great thing about doing it this way is that you can put data annotations attributes to your application model class and get your posted objects automatically validated, so you don't have to do this yourself.