MVC Create method data flow - asp.net-mvc

I think i know some of the basics of MVC but there's one thing which I don't understand yet.
In the view Create which is generated automatically when you set up your project, how is data sent to the controller? I'm used to seeing ActionLinks with parameters but here there's no actionLink so I can't understand how data travel from the view to the controller.
Could you explain it to me please?

as you know, in your view, the very first line (usually) tells the view, about the Model being used within this view. like:
#model Models.CarViewModel
lets suppose, you have a form on this view, and it is posted to some action called Edit. Then you must have your Edit action, expecting the parameter of type you used as model in your view. like:
[HttpPost]
public ActionResult(CarViewModel model)
{
//logic
}
This convention is known as Strongly Typed View. Suppose Then you have some textbox for a property Name of your model as:
#Html.TextBoxFor(x => x.Name)
when the form is posted to Edit Action, the variable model in parameter of Edit action will be holding the respective values. i.e, model.Name

Related

ASP.NET MVC Tuple

In my View i have to put two different Forms and i have to use two different ViewModels. So i decided to use Tuple.
View:
#model Tuple<pi.Models.AddNewMechanic,pi.Models.ExistingUser>
and I got two forms
But how can i recive it from View in HttpPost Controler?
I tried like that:
public ActionResult AddMechanic(Tuple<pi.Models.AddNewMechanic, pi.Models.ExistingUser> model) {}
but i got message it cannot find method with parameter, so how I have to implement it inside this method, but there is a question how?
I strongelly sugest you create a new Model and inside of your new model, you can put this two object. Take care to dont mix domain model and view model. Otherwise, you will have always this kind of problem.
Domain Model
- class a
- class b
View Model
- class AB
prop A, prop B
I suggest you do this by the book, which would be:
AddMechanic.cshtml has no special view model, but contains two partial views. This is your "page with two forms".
_AddNewMechanic.cshtml is the first partial view form, which has AddNewMechanic as view model.
_ExistingUser.cshtml is the second partial view form, which has ExistingUser as view model.
The form in _AddNewMechanic.cshtml posts to the AddNewMechanic action method, which takes an AddNewMechanic as parameter.
The form in _ExistingUser.cshtml posts to the AddExistingMechanic action method, which takes an ExistingUser as parameter.
Upsides:
No need for any Tuple weirdness.
You can keep your existing View Models.
Your action method parameters will not normally be null, so no need for weird null checks.
Easy to follow and understand your code.

Render a partial view with single model from a partial view using an IEnumerable

I am trying to figure out how to render a single model from a view that is using an IEnumerable of that model. I can't seem to figure out how to send it using the razor
Right now I am getting the error:
MyApp.Models.DefectsVM' is a 'type' but is being used like a 'variable'
On this line in my main view(Under DefectsVM model I am trying to pass in):
#{Html.RenderPartial("~/Views/Defect/defectsPartial.cshtml", DefectsVM);}
My partial view has this in it to use a model:
#model MyApp.Models.DefectsVM
And my main view is using this:
#model IEnumerable<MyApp.Models.DefectsVM>
I am not sure what all other information is needed, let me know if I need to edit. But thank you for reading and taking your time to help.
You need to refer to your model with Model. But in your case, Model will return an IEnumerable<MyApp.Models.DefectsVM>, so you will need to iterate over that, and then render your partial.
Something like:
foreach(var defectsVM in Model)
{
#{Html.RenderPartial("~/Views/Defect/defectsPartial.cshtml", defectsVM);}
}
Regardless of whether the IEnumerable contains one or more than one, it should work.

PartialView causing error

I have created a partial view which returns a list of items where the ItemsId matches the one passed to it.
//
// GET: /ItemOptions/Item/5
public ActionResult Item(int id = 0)
{
var itemoptions = db.ItemOptions.Where(o => o.ItemsId == id);
return PartialView(itemoptions.ToList());
}
I am trying to display this on the details page of the parent item using the following code:
#Html.Partial("../ItemOptions/Item", Model.ItemsId)
If I visit {URL}/ItemOptions/Item/1 it returns the table I am expecting to see. But if I navigate to the parent item where I am trying to include the partial view I get the following error:
The model item passed into the dictionary is of type 'System.Int32', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[shopServer.Models.ItemOptions]'.
I have read other posts but can't work out where I am going wrong. I also read that I may need to use #Html.Action instead of Partial views, but I am unsure which is appropriate in which situation.
The method Html.Partial is directly rendering the partial view (without executing the controller logic), using the object passed in the second parameter as the model instance. So as the error says, the code line #Html.Partial("../ItemOptions/Item", Model.ItemsId) is trying to render your partial view using an integer (Model.ItemsId) as the model, but your partial view expects IEnumerable[shopServer.Models.ItemOptions].
You have 2 options for resolving your issue, depending if the data for the partial view is already loaded in the model for the parent view or not.
If in the parent view the model already contains the collection of item options, then you can just pass them to the partial view using the Html.Partial method. So assuming you could have a property like ItemOptions in the model of your parent view, then you could render the partial as:
#Html.Partial("../ItemOptions/Item", Model.ItemOptions)
If that is not possible, and the data you need for the partial view is unknown to the parent model, then you need to execute the controller logic (so you can populate the model for the partial view retrieving the extra data from the databaes.) In that case what you need is a child action, achived using the method Html.Action. You will need to pass the controller name, action name and parameters for the action method as in:
#Html.Action("Item", "ItemOptions", new {id = Model.ItemsId})
With the second option, the logic in the controller action method is executed, retrieving the ItemOptions from the database, rendering the partial view and including the resulting html into your main view.
You can find a quick rule of thumb for Html.Partial and Html.Action usage `here.
Hope that helps!

ASP.NET MVC flow (how are the models created, populated and passed around)?

I've seen flow charts of the life-cycle but they never seem to answer this question OR I'm just not getting it.
So if user hits a registration page is it:
Routing engine chooses controller.
Controller checks to see which view should be displayed, checks to see if it is strongly typed and if so instantiates the correct model.
Calls the View, passing the empty model in.
I'm also interested in what happens when the form is filled out and submitted.
I'm not looking for anything super technical, just something conceptual...
Regardless of the user actions (followed the link, entered the URL, submitted the form) the basic flow of the MVC application is the following:
According to the routing table Controller's name and method (aka Action) that will handle the request are defined.
If there were any request parameters (values in form for example) they are associated with the Action's parameters.
Request context is generated (contains details about request, client, server, etc.)
Object of Controller's type is created, Action (method) of this object is called with given parameters.
After processing, Action returns an appropriate result, most likely View (could also be Json, plain text, anything).
View is rendered and send back to the client as a response.
Of course, a lot of details are left aside here, but this is the general conception.
Update: some words about models.
Models are used to pass data from the Controller to the View. There are two main approaches:
Using ViewData collection - basically a regular key-value dictionary. In Controller it is filled with data:
ViewData["SomeKey"] = "someValue"; //not only string, any object can be here
return View();
And in View values are retrieved by keys:
<%= ViewData["SomeKey"] %>
Strongly typed Views. A Model class that will contain necessary data is created. View is specified to be strongly typed with this class, and when Action returns a View object, it passes an instance of this class as a parameter. Here is some code example:
Model:
public class SomeModel
{
public string SomeKey { get; set; }
}
Controller:
SomeModel model = new SomeModel();
model.SomeKey = "someValue";
return View(model);
View:
<%# Page ... Inherits="System.Web.Mvc.ViewPage<SomeModel>" %>
...
<%= Model.SomeKey %>

I have a ViewModel strongly bound to my View in my ASP.NET MVC app, now what about the controller

So like the title says, I created a view model in my asp.net mvc application so it would be strongly typed to my view. My view model is a combination of two of my model classes. Now when the user hits the save button on that view, it goes to a controller. How does it know what controller to go to? I built my controller 1 - 1 so to speak with my models and views so controller A knows about Model A and controller B knows about Model B. But if I have a view model that is AB how does it know on subit to go to A or B. Do I need a controller called AB Controller?
The controller and action invoked do not depend on the viewmodel object you used to bind the page during initial view rendering. The controller (and action) invoked is determined by the URL of the request sent. (One of the routes you have defined will be matched based on the URL string of the request or a 404 not found error will be returned.)
A submit button in an HTML form (usually a POST) will have an action attribute that determines its url target, an anchor tag will have an href, etc.
In your situation where you have a custom viewmodel object you can define an action to expect and to attempt to parse that specific type of object by specifying it as the parameter to your action:
public ActionResult SaveSystemSetting(SystemAdminVM item) {
An Action Method doesn't receive a model. It receives parameters.
Anyway I think I know where you come from: One of the parameters of your action has the type of the ViewModel used in the View. That is a common layout and makes a lot of sense. In lots of projects it is so widely used that after some time you start to think that an action actually receives a model.
Just remenber that the parameters of your action can by anything that can by filled by the ModelBinder. You could pass both Models as parameters, you could pass a ViewModel that agregates Model a and b or you could pass a ViewModel that has properties of a + b.
Agregation ist the most common approach.
Generally we overload our action methods in the controller so if you have an action called edit that renders the view with your viewmodel object, you will have an overloaded edit action method with the HttpPost specified for that method.
The data to this method will be passed as form value collection values or you can bind it to your viewmodel object if you like and process it further.

Resources