Bind/map response to more than one object - asp.net

I am new to MVC. I have a controller ActionResult that has various incoming requests from various parties. I want this ActionResult to figure out what type of request it is, validate it, and perform several RedirectToAction.
My problem is that while I know how to bind a single model/object to an ActionResult and have the framework automatically map the variables from the request to that model's properties, I don't know how to achieve the same "automapping" functionality when I need to map the same request to several models that are completely separate from each other inside a single ActionResult. I am unable to determine what models are contained inside the request until I map them and validate them, by checking if the models' properties are not null.
Any thoughts?

You should really create different Actions. Since the models that are passed in are different you cannot bind them to the same action.
Of course, what you could do is create different action methods, and from there on just call a single method that contains all of your logic

If you have access to the different model classes you could create an interface that they implement, and use this interface as the model type in your controller method.
Then you could create a custom model binder and do your checking of properties there.

Related

Bind to multiple parameters without using a view model

If I'm posting some variables to a Web API method, is it possible to do this without creating a view model?
It seems that you can only bind to a single parameter (which represents the request's body), so if there are multiple variables then that necessitates a view model to contain them.
You can only have one param decorated with [FromBody], so therefore that one param must encapsulate all the data coming from the request body.

ASP.Net MVC - ModelState.AddModelError when GET/POST have different models

I have a use case where I used different models for the GET and POST actions in my controller. This works great for my view, because most of the data goes into labels. The model for the GET method contains 10 properties, but the model for the POST method only needs 3.
This GET view renders a form, which only needs 3 of these properties, not all 10. Thus, the model for the POST method accepts a model class which contains only these 3 properties. Therefore, the ASP.Net MVC model binder populates the model class parameter on my POST method with only these 3 necessary properties, and all is well.
Here's the question: When I encounter some business rule violation in the POST method, and want to use ModelState.AddModelError, and re-display the original view, I no longer have the 7 properties that were not POSTed, as they were not part of the form, and are not part of the model class which this method takes as its parameter.
Currently, I'm calling into a builder to return an instance of the model class for the POST method, and have the GET method itself delegating to the same builder. So, in these cases, when there is some business rule violation in the POST method, I return a View("OriginalGetView", originalGetModel). How can I use ModelState.AddModelError in this case, in the POST method, if I want to send custom messages back to the view, using a completely different model class?
It seemed way too lazy to use the same model class for both the GET and POST methods, given that their needs were so different. What is the best practice here? I see a lot of people recommending to use the same model for both methods, and to POST all of the fields back from hidden form fields, but that just seems like a waste of bandwidth in the majority of cases, and it feels ugly to be sending things like "VendorName" back to the server, when I already have "VendorId".
I may be misunderstanding what you are trying to do, but make sure you aren't being penny-wise and pound foolish. I see you may only want to post the identifiers and not necessarily the descriptors. But it sounds like you have to re-display the view after posting...if so you can just access the model properties if you post the same model that is in the get. If you only post the identifiers, you have to spend time re-accessing the database to get the description values(i.e. vendorname as you describe) using the vendor id no? Wouldn't that also be extra processing? Like I said, I could be misunderstanding your post, but for consistency using the same view model for your view to get and post makes the most sense to me.
Hidden Inputs maybe the best solution here still I think, even on 2g you shouldn't create any lag unless unless the values of your Model properties are long strings or something encrypted or xml.
So your .cshtml would have this in it for the 4 properties not currently included in the form:
<form>
#Html.HiddenFor(m => m.Property1)
#Html.HiddenFor(m => m.Property2)
#Html.HiddenFor(m => m.Property3)
#Html.HiddenFor(m => m.Property4)
But you could also get the model state errors from the original posted model and recreate the ModelError state in your response model to get around using hidden inputs.
I just found this guide (not the answer with Green Checkmark but the highest upped Answer: ASP.NET MVC - How to Preserve ModelState Errors Across RedirectToAction?
Note: if you need to copy model properties from Model to another Model (of the same type or different type), in a cleaner way, check out AutoMapper.
Perhaps this could help with what you were trying to achieve - 'Model' level errors - which wouldn't need to attach to a specific field/property - but can be displayed in a Global area.
https://stackoverflow.com/a/53716648/10257093

With Microsoft's WebAPI, is it possible to have multiple POST methods in one controller?

I notice that the method created by the scaffolding is called POST and that there are not [HttpPost] attributes on it. If I want to create multiple POST methods, like in my case I want to have a controller named "Register" and I want to have one method called "RegisterAttendee" and another called "RegisterSpeaker". I want them to have different protection levels so I want two different method calls.
Is that possible with WebAPI like plane old MVC controllers with the [HttpPost] attribute?
Yes you can define multiple posts in a controller with [httppost] attribute. However you only need to use that attribute when your method name doesnt start with Post. You can differentiate between different Post calls by different number of parameters and/or by defining routes in your config.
Hope this helps.

asp.net mvc3 / razor view best practices

I am using in my views (asp mvc3/razor cshtml) references to the Request object (eg, #Request.Params["Name"]). Do you think this is a very bad practice? Should I rewrite the value in the controller Request.Params ["Name"] to ViewBag.Name and then use it in the view (#ViewBag.Name)?
Best practice is to use a model class. An instance of the model class is created or updated in your controller. Then the controller displays a strongly-typed view.
So I'd avoid direct access to the request from the view as well as the use of the view bag.
Should I rewrite the value in the controller Request.Params ["Name"] to ViewBag.Name and then use it in the view (#ViewBag.Name)?
Yes. You will avoid runtime errors if "Name" does not exist.
The IDE will not warn you of the NullReferenceException about to be thrown with the following code.
#Request.Params["Fake"].ToString()
Of course, you'll have to be careful about ViewBag.Fake being null as well.
I like to use the viewbag to store things not related to the model, for example if I have a dropdown containing locations. I like to store only the id of the selected location on the model and the locations in the viewbag, since is not needed to create a contact. I think that's the purpose of the viewbag.
For me the model is a bag or properties used in business operations, for example if I have a customer creation view using a NewCustomerModel, I don't wanna pollute my model with things like a IList<CustomerType> AND a SelectedCustomerTypeId property. I just want the second since is the one imma use to create the customer.

Fat ASP.NET MVC Controllers

I have been reading about "Fat Controllers" but most of the articles out there focus on pulling the service/repository layer logic out of the controller. However, I have run into a different situation and am wondering if anyone has any ideas for improvement.
I have a controller with too many actions and am wondering how I can break this down into many controllers with fewer actions. All these actions are responsible for inserting/updating/removing objects that all belong to the same aggregate. So I'm not quiet keen in having a seperate controller for each class that belongs to this aggregate...
To give you more details, this controller is used in a tabbed page. Each tab represents a portion of the data for editing and all the domain model objects used here belong to the same aggregate.
Any advice?
Cheers,
Mosh
For all your tabs you can use one action, that have an tab parameter, that indicate what data you need to return.
The controller job is to cast this string tab into enum type variable. Then the tab will be send to the repository, and the repository job is to return data in response to the tab value.
The controller should do its job through to services: Input Validator and Mapper.
The mapper service job is to map the user input (typically strings) into actual typed value (int, System.DateTime, enum types, etc).
The validator job is to check that the input is valid.
Following this principles should keep your controllers really tiny.
If you wanted something simple and easy I'd suggest just splitting up the controller into partial classes based on the tabs. Of course, it's still a fat controller there's just some obvious separation between the various tab functionalities.

Resources