ASP.NET MVC and submitting different models to an Action - ajax

I have a scenario where I have a list of filters that inherit from the same base class (BaseFilter). This are rendered in a few with different templates in a certain order based on what the user chooses. What is the best way to grab that data via javascript and submit it via an ajax request to a strongly typed List<IBaseFilter> in the ActionResult. Should I use a model binder and if so how with a list of IFilters?
public ActionResult Save(List<IFilter> filters)
{
}
public FirstFilter : BaseFilter {
// Has Two Properties
}
public SecondFilter : BaseFilter {
// Has One Property
}

Casting from child to parent means that you loose all child properties, and you only get parent properties. If you model bind filters to IFilter then only properties existing in IFilter would be available to you. I recommend that you create two action methods, and save filters consecutively, if possible, and use strongly-typed model binding in those actions. Another options might be to send data to the action method, but extract information manually from HTTP request, rather than letting ASP.NET MVC bind incoming parameters to your List<IFilter> parameter.

Basically Binders get what's in the FormCollection, and convert them to nice model objects for you. You probably can create a customized binder (IModelBinder implementation) to do all that for you. See this post to get an idea on how they work.

Related

How to store variables in all pages requestScopes within Spring

I usually add objects in my jsp requestScopes using Controllers.
For example, if I need to list categories in "localhost/products/viewall", I simply change my ProductsController adding something like
#RequestMapping("/products/viewall")
public void viewCategories(Model model) {
List<Category> categories = service.findAllCategories();
model.addAttribute("categories", categories);
}
so, this method adds a list of categories to my requestScope.
I need to do the same, but for all the pages of the website (since the variable I need will be used in the layout of the site).
How can I add something to all the pages requestScopes with Spring?
I think you have at least two possible options for this:
Using an MVC Interceptor. With an interceptor you can perform common operations for all requests. You can extend HandlerInterceptorAdapter and add common model data in postHandle
Using the #ModelAttribute annotation within an Controller. You can use this to add common data for all request mappings within a controller. You can also use an #ControllerAdvice (with #ModelAttribute annotated methods inside) if you want provide model data to all controllers. The section Using #ModelAttribute on a method should provide some additional information for this.

ASP.NET WebAPI: Generic controller for OData endpoint

I'm currently experimenting with OData endpoints in ASP.NET MVC 4 Web API. I like the concept and try to come up with efficient ways to use it in our project.
One question I have is the following: we have a service that is able to return an IQueryable and takes the name of an entity as Input:
public IQueryable GetAll(string entityName);
In standard Web API (as opposed to OData Controllers) I can create a generic controller, that can be called in the form /api/entities/{entityName} and returns the IQueryable.
In case of an OData Controller, I carry out the following entity-specific steps:
Register the entities in the model.
Create a separate Controller for each entity that derives from EntitySetController<>.
I want to use the generic service and avoid as much entity-specific implementations as possible. The first step can easily be automated if the service can return a list of the entities and the corresponding types.
That leaves step 2, because up to now I need to create a specific controller for each entity. I also want to avoid that and create a generic controller that uses the generic service.
Can anyone recommend a solution, maybe by influencing OData routing?
You can create a custom routing convention that selects the same controller no matter what the entity set is. Example,
public class CustomControllerRoutingConvention : IODataRoutingConvention
{
public string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup<string, HttpActionDescriptor> actionMap)
{
return null;
}
public string SelectController(ODataPath odataPath, HttpRequestMessage request)
{
return "SomeFixedContrllerNameWithoutTheControllerSuffix";
}
}
You can register that routing convention using the following code,
IList<IODataRoutingConvention> routingConventions = ODataRoutingConventions.CreateDefault();
routingConventions.Insert(0, new CustomControllerRoutingConvention());
config.Routes.MapODataRoute("OData", "odata", builder.GetEdmModel(), new DefaultODataPathHandler(), routingConventions);
I came up against the same problem, and ended up writing a custom IHttpControllerSelector instead of an IODataRoutingConvention. IODataRoutingConvention looks like a good option if your generic controller doesn't require generics :) . But since IODataRoutingConvention.SelectController() only returns a string, I don't see how it will work for instantiating a controller with generic type parameters.
I decided this problem needs a good, general-purpose, open-source solution - so I created one: https://github.com/EntityRepository/ODataServer . It's prerelease now, but I'm currently doing a lot of work on it. I think there's more to it than just choosing the right controller, there are general patterns to define for shared controllers, and by default Web API OData expects strongly typed and strongly named navigation properties which makes it challenging to create a re-usable implementation.

WebApi: how to pass state from filter to controller?

I am pulling some user data in action filter, and could use some of that data in a controller's action, but not exactly sure how to pass data from a filter to a controller.
In MVC I'd probably use session or HttpContext.Items, but it's not available in web api. Another option is to use ThreadStatic, but I think there has to be a better solution?
You can use Request.Properties dictionary to do that.
In the filter:
MyType myObject = //initialize from somwhere
actionContext.Request.Properties.Add("mykey", myObject);
And then you can retrieve it in the controller:
object myObject;
Request.Properties.TryGetValue("mykey", out myObject);
//cast to MyType
The advantage of this approach is that the current request instance is available everywhere in the Web API pipeline, so you can access this object i.e. in the Formatter or MessageHandler too.

Work flow of simpleFormcontroller in spring MVC 3.0

I have seen many examples on how simpleFormcontroller works.
But still I have some confusion.
I want to know when formBackingObject(), referenceData(), onSubmit() methods invoked?
I dont know exact working flow of these methods?
Can anyone explain me?
Workflow is as follows and it is controlled by AbstractFormController class-
The controller receives a request for a new form (typically a GET).
Call to formBackingObject() which by default, returns an instance of the commandClass that has been configured (see the properties the superclass exposes), but can also be overridden to e.g. retrieve an object from the database (that needs to be modified using the form).
Call to initBinder() which allows you to register custom editors for certain fields (often properties of non-primitive or non-String types) of the command class. This will render appropriate Strings for those property values, e.g. locale-specific date strings.
Only if bindOnNewForm is set to true, then ServletRequestDataBinder gets applied to populate the new form object with initial request parameters and the onBindOnNewForm(HttpServletRequest, Object, BindException) callback method is called. Note: any defined Validators are not applied at this point, to allow partial binding. However be aware that any Binder customizations applied via initBinder() (such as DataBinder.setRequiredFields(String[]) will still apply. As such, if using bindOnNewForm=true and initBinder() customizations are used to validate fields instead of using Validators, in the case that only some fields will be populated for the new form, there will potentially be some bind errors for missing fields in the errors object. Any view (JSP, etc.) that displays binder errors needs to be intelligent and for this case take into account whether it is displaying the initial form view or subsequent post results, skipping error display for the former.
Call to showForm() to return a View that should be rendered (typically the view that renders the form). This method has to be implemented in subclasses.
The showForm() implementation will call referenceData(), which you can implement to provide any relevant reference data you might need when editing a form (e.g. a List of Locale objects you're going to let the user select one from).
Model gets exposed and view gets rendered, to let the user fill in the form.
The controller receives a form submission (typically a POST). To use a different way of detecting a form submission, override the isFormSubmission method.
If sessionForm is not set, formBackingObject() is called to retrieve a form object. Otherwise, the controller tries to find the command object which is already bound in the session. If it cannot find the object, it does a call to handleInvalidSubmit which - by default - tries to create a new form object and resubmit the form.
The ServletRequestDataBinder gets applied to populate the form object with current request parameters.
Call to onBind(HttpServletRequest, Object, Errors) which allows you to do custom processing after binding but before validation (e.g. to manually bind request parameters to bean properties, to be seen by the Validator).
If validateOnBinding is set, a registered Validator will be invoked. The Validator will check the form object properties, and register corresponding errors via the given Errors object.
Call to onBindAndValidate() which allows you to do custom processing after binding and validation (e.g. to manually bind request parameters, and to validate them outside a Validator).
Call processFormSubmission() to process the submission, with or without binding errors. This method has to be implemented in subclasses.
Source
For more details and diagrammatic representation to understand the flow you can refer to below link -
SimpleFormController is deprecated since Spring 3.0
In Spring 3.0 use one controller with two methods for the creation process (and a third one for the show page). It typical looks like that:
/**
* Shows a form for car creation.
*/
#RequestMapping(params = "form", method = RequestMethod.GET)
public ModelAndView createForm() {
ModelMap uiModel = new ModelMap();
uiModel.addAttribute("carCreateFormBackingObject", new CarCreateFormBackingObject()); //formBackingObject - often called command object
uiModel.addAttribute("manufactureres", this.manufactureresDao.readAll()); //referenceData
return new ModelAndView("car/create", uiModel);
}
/**
* Creates the car and redirects to its detail page.
*
*/
#RequestMapping(method = RequestMethod.POST)
public ModelAndView create(final #Valid CarCreateFormBackingObject carCreateFormBackingObject,
final BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
ModelMap uiModel = new ModelMap();
uiModel.addAttribute("carCreateFormBackingObject", carCreateFormBackingObject);
uiModel.addAttribute("manufactureres", this.manufactureresDao.readAll()); //referenceData
return new ModelAndView("car/create", uiModel);
}
Car car = this.carService.create(carCreateFormBackingObject.name, ...);
return new ModelAndView(new RedirectView("/cars/" + car.getId(), true)); //redirect to show page
}
still i want to know formBackingObject(),refernceData() method get invoked automatically by whom and when?
Back to your question "still i want to know formBackingObject(),refernceData() method get invoked automatically by whom and when?"
All these methods get invoked by SimpleFormController (and its superclass AbstractFormController), the follow the Template-Method-Pattern. - SimpleFormController defines the process and your concrete subclass "plugsin" in some hooks of this process to gain the business value.
formBackingObject in invoked by AbstractFormController when the controller needs to handle a Submit (POST), or build the Command object for the initial "new" view.
referenceData is always invoked AbstractFormController when it need to build the model for the view.
formBackingObject() method, is used when you want to take some action before rendering page. i.e. like default value in HTML components.
refereceData() method, is used for add reference data in your form, i.e. populating dropdowns
OnSubmit() method, is called whe you submit form.
But, if you are using Spring 3.0
Follow following approach using annotation
#RequestMapping(value = "/index.htm", method = RequestMethod.GET)
public String showLogin() {
return "user/login";
}
This will same as formBackingObject. and in this method use modelMap() and add reference data.
Add methods same way with method = POST which will be same as OnSubmit()
rfe folling link
http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/web/servlet/mvc/SimpleFormController.html
Read Workflow.. you can simply understand your doubts..
FormBackingObjectMethod()---> #RequestMapping(requestMethod.GET)
while first time form shown to the screen formBackingObject is the reason
initBinder()---> normally used for suppose you want date field should be for example (custom date example : dd**MM***yyyy) needed means use initBinder method
onSubmit() -->#RequestMapping(requestMethod.POST)
while submitting the form onSubmit() method get called
i hope this helps

How to control the model binding security if i am passing an Object to a post edit Action method in asp.net mvc

i found a lot of examples and tutorial in professional websites that implement a post action method as follow by passing an Object instead of passing the object ID:-
[HttpPost]
public ActionResult Edit(Album album)
{
if (ModelState.IsValid)
{
db.Entry(album).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction(“Index”);
}
but on the other hand it is recommended for security reasons to define a Bind list on the model object level such as
[Bind(Include="Title,Description,genere")]
to prevent the model binding from manipulating object’s properties related to; ID , navigation properties or other properties such as createdby ,etc. and instead we should only
manipulate these particular properties using explicit code within our action methods.
But the above approach of implementing the post action method by passing it a model object will conflict with defining a Bind list, so how i can handle such situation ?
You don't need to handle any situation, the Bind attribute will ensure that only these properties can be updated from the posted model.

Resources