How to post List of Dictionary - asp.net

I have a client ( in this case POSTMAN) that is posting collection of object. The properties of the object are not known in advance so I cannot use concrete C# model.
So I am using Dictionary<string,object> that represent a single object where Key will be the property name and Value will be the value of the property. Since client is posting collection i am using List<Dictionary<string,object>>
ISSUE
In controller's action method each dictionary has Key however corresponding value is NULL
POSTMAN
Fiddler shows
model%5B0%5D.FirstName=foo&model%5B0%5D.LastName=bar&model%5B1%5D.FirstName=james&model%5B1%5D.LastName=smith
Quick watch in model:
I tried using JObject, ExpandoObject as model with no luck

I changed the model type from List<Dictionary<string, object>> to List<Dictionary<string, string>> and it worked
[HttpPost]
public IActionResult Update([FromForm]List<Dictionary<string, string>> model)
{
return Ok();
}

Related

Use of Model object as a param in the request handling methods

I just want to know
Why do we use Model object as a Parameter to the request handling method in the Spring MVC application?
Basic Explanation helps me a lot.
ModelAndView (or Model) is a specialized spring object to store name value pairs (kind of java Map). It is optional to have the Model Object as a parameter to the request method. However in case if your request method has anything that needs to be passed on to the View; then you need a Model.
So Model is basically a data structure that carries information from the service layer to the view layer.
You can also initialize a Model inside your request method as:
public ModelAndView listCarrier() {
HashMap<String, Object> model = new HashMap<String, Object>();
model.put("isView", request.getParameter("isView"));
return model;
}
You can add attribute to Model object and use that attribute inside your JSP like below.
#RequestMapping(method = RequestMethod.GET)
public String login(String name, Model model) {
model.addAttribute("name", name);
return "xyz";
}
and later on you can access this property in your xyz.jsp like below.
Name: ${name}
For more info refer :-Model API docs

RedirectAttributes changes object id between controllers

I am using Spring MVC and Hibernate in my project. Also I have 2 controllers UserController and BookController where BookController redirects to the users page and I am passing a Book object in addition.
I've found I can do this with RedirectAttributes but the problem is that the id of the passed Book object is changed during this transition to user.id.
BookController.java
public class BookController {
#RequestMapping("/users/{user_id}/books/edit/{book_id}")
public String editBook(#PathVariable("user_id") int user_id, #PathVariable("book_id") int book_id, final RedirectAttributes redirectAttrs){
bookDetail = this.bookService.getBookById(book_id)
redirectAttrs.addFlashAttribute("bookDetail", bookDetail);
System.out.println(bookDetail);
return "redirect:/users/"+user_id;
}
}
Prints: id=8, title=Motylek, description=Some description, user_id=2.
UserController.java
public class UserController {
#RequestMapping("/users/{id}")
public String detailUser(#ModelAttribute("bookDetail") Book bookDetail, #PathVariable("id") int id, Model model){
User u = this.userService.getUserById(id);
model.addAttribute("user", u);
model.addAttribute("bookDetail", bookDetail);
System.out.println(bookDetail);
return "user";
}
}
Prints: id=2, title=Motylek, description=Some description, user_id=2.
Do you have and idea why this happens or is it a bug? Thanks.
I'm going to assume that your Book class has a property called id, ie. a getter or setter called getId() and setId(..).
When Spring parses the request URL, it stores path segments as declared in the corresponding #RequestMapping. So for
/your-app/users/2
and
#RequestMapping("/users/{id}")
It will store
id=2
as a request parameter.
Spring will then proceed to generate an argument for
#ModelAttribute("bookDetail") Book bookDetail
It will check the various request, session, servlet attributes for an entry with the name bookDetail. (If it doesn't find one, it will create one and add it to the request attributes.) In your case, it will have found the object in the HttpSession. It will then bind any request parameters to matching object properties. Since the parameter above is called id, it will be bound to the Book property id.
You should be good by changing
#RequestMapping("/users/{id}")
to
#RequestMapping("/users/{user_id}")
along with the corresponding #PathVariable.

How does ASP.NET MVC pass model to the view without explicitly passing it

Here is one of the examples that I've seen on how to do validation on Controller:
[HttpPost]
public ViewResult Create(MyModel response)
{
if (ModelState.IsValid)
{
return View("Thanks");
}
else
{
return View();
}
}
If there are validation errors, than return View() method is called without any parameters. Obviously you have #Html.ValidationSummary() in your View and Model has all required property attributes.
The data that was entered into the form was preserved and displayed again when the view was rendered with the validation summary.
My question: how is the data preserved? Since it was not passed to the View like
return View(response);
Thanks a lot.
Sincerely,
Vlad
It is because the values have been bound to the model state which is passed back along to the view. This is along the same issue/question on why you cannot change a model value and return the view again. Meaning, let's assume I have the following property on my Viewmodel
public string Name {get;set;}
Using the controller below, I cannot change the ViewModel property without also either clearing the ModelState or updating the value in the model state. Try it!
[HttpPost]
public ViewResult Create(MyModel response)
{
response.Name = response.Name + "Some Random String"
return View();
}
The name property will remain unchanged. Essentially, once the ModelBinding occurs, the values from your form (ViewModel) are bound to the model state, which is why you do not have to pass the model back to the view.
As a side note, I always pass the model back in my call to return View();, it just seems more correct and a little easier to read

What does it mean when Spring MVC #Controller returns null view name?

I downloaded the code for the Spring MVC 3 Showcase. One thing puzzles me (well, more than one), why does this (edited for concision) sample return null?
#Controller
#RequestMapping("/form")
public class FormController {
#RequestMapping(method=RequestMethod.POST)
public String processSubmit(#Valid FormBean form,
BindingResult result,
WebRequest webRequest,
HttpSession session, Model model) {
if (result.hasErrors()) {
return null;
} else {
session.setAttribute("form", form);
return "redirect:/form";
}
}
}
If a controller returns a null view name, or declares a void return type, Spring will attempt to infer the view name from the request URL.
In your case, it will assume the view name is form, and proceed on that assumption.
It does this using an implementation of RequestToViewNameTranslator, the default implementation of which is DefaultRequestToViewNameTranslator, the javadoc for which explains the exact rules it applies.
AnnotationMethodHandlerAdapter.invokeHandlerMethod() takes care of invoking handler methods. Here, a ModelAndView will be retrieved via ServletHandlerMethodInvoker.getModelAndView().
In your case, getModelAndView() gets provided the handler method's null return value. The getModelAndView() method checks for the return value's type, but as in Java null is never an instanceof any class, that method's logic will create a new ModelAndView. A new ModelAndView has initially its view property set to null.
Then later back up the call stack, in DispatcherServlet.doDispatch(), there is a test if the ModelAndView object has a View associated with it ( mv.hasView() ). Because view == null, doDispatch()'s logic calls mv.setViewName(getDefaultViewName(request)). It delegates to the registered RequestToViewNameTranslator, whose default implementation is DefaultRequestToViewNameTranslator. This subclass translates the request URI into a view name, in your case form.
Later in doDispatch(), via render() -> resolveViewName(), this sample's ViewResolvers are provided with the view name form. Only one ViewResolver, InternalResourceViewResolver is used in this sample. Also, this InternalResourceViewResolver was configured in src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml to add the prefix /WEB-INF/views/ and the suffix .jsp to the view name. So in total, it will create a View using the JSP file /WEB-INF/views/form.jsp. Luckily, a JSP file exists at exactly this location.

ASP.NET MVC: No record added to database after POST

[HttpPost]
public ActionResult Create(FormCollection collection)
{
UpdateModel(collection);
context.SaveChanges();
return RedirectToAction("Index", new {controller = "Home"});
}
The action succeed, but there was no recored inserted into the database. Why?
I do not want to manually create a object by getting each value from each field in form collection.
UpdateModel(collection);
context.SaveChanges();
You didn't made any changes to the context in order to expect something to get saved. Entity Framework (assuming this is what you are using) works with objects. So you need a model and persist this model into the database. So your controller action could look like this:
[HttpPost]
public ActionResult Create(Product product)
{
_repository.Create(product);
return RedirectToAction("Index", new {controller = "Home"});
}
where the _repository variable is some interface which defines the operations on your models. Using an interface here allows you to separate your data access logic from your controller logic. In the implementation of this repository you could be using any data access technology you like such as EF or NHibernate, it's just that your controller shouldn't know about it.
Are you sure the context is open and it's the same from which your object has been extracted ? is the object is still connected to the context ?
usually you create a new context in each call, you need to attach the object to the context change it state to modified and than use SaveChanges.
Otherwise, nothing is done.
context.Customers.Attach(myCustomre);
context.ObjectStateManager.ChangeObjectState(myCustomre, System.Data.EntityState.Modified);
context.SaveChanges();
and for insert:
context.Customers.AddObject(newCustomer);
context.SaveChanges();

Resources