In my controller, my create method takes a viewModel that inherits from DynamicObject. The reason is that I need static properties on the model, but I may also add things to it via JavaScript before I pass it to the controller.
So, I have:
public class MyViewModel: DynamicObject {
public string id {get;set;}
}
[HttpPost]
public IHttpActionResult Create(MyViewModel viewModel) {
// save to Db
}
From the JavaScript (using Angular), I've passed in this viewmodel:
var vm = { id: 1, name: "Jim"};
However, this does not work and is throwing me this error:
[{"PropertyName":null,"ErrorMessage":null,"ErrorCode":null,"AttemptedValue":null,"CustomState":null}]
I haven't found an example of what I'm trying to do, but I would think making an object dynamic would allow for this. What am I missing here?
Related
So I have model entity Place that has to have initialized some relations.
Now I am using autocreated model form-backing bean in controller as follows:
#GetMapping(value = "/add")
public String addPlacePage(final Place place, Model model) {
model.addAttribute("services", serviceRepository.findAll())
.addAttribute("categories", categoryRepository.findAll())
.addAttribute("cities", cityRepository.findAll());
return "admin/place/addPlace";
}
Place place is created my Spring (Spring-MVC probably). Is there a way to provide a factory method for backing bean? I would like to not to do this in controller.
I have tried to put factory code in my configuration like this:
#Bean
#Scope(value = "prototype")
public Place place() {
log.info("Creating place in FACTORY");
Place place = EntityFactory.emptyPlace();
return place;
}
but this does not work.
So I have ask the same question in #spring channel on freenode, and this is something that came up thanks to user <#_ollie>. In order to do what I want, #ModelAttribute method should be defined in controller like this:
#ModelAttribute
private Place emptyPlace(){
log.info("Creating place in FACTORY");
Place place = EntityFactory.emptyPlace();
return place;
}
and related docs are here
https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-ann-modelattrib-methods
I am using the following viewModel on my view:
public class CourseViewModel
{
public IEnumerable<Course_page> Course_page { get; set; }
public IEnumerable<course_section> Course_section { get; set; }
public IEnumerable<course_subsection> Course_subsection { get; set; }
public IEnumerable<Enrollment> Enrollments { get; set; }
}
In my view I have the following ajax form:
#using (Ajax.BeginForm("updateprogress", "User", new { EnrollmentID = Model.Enrollments.Single().EnrollmentID }, new AjaxOptions
{
HttpMethod = "POST",
}, new { id = "ajaxForm" }))
{
#Html.HiddenFor(Model => Model.Enrollments.Single().progress1, new { id = "scenecheck" })
}
I have an animation generated by a program called Hype, within the animation are scenes and the current scene number is called using a javascript function with the value populating the form above in the 'progress1' field:
function updateprogress(hypeDocument, element, event) {
var scenenumber = hypeDocument.currentSceneName();
hypeDocument.getElementById('scenecheck').value = scenenumber;
$('form#ajaxForm').submit();
}
I have some other javascript which listens for the scene change and calls the function above whenever it does change.
When I change HiddenFor to TexboxFor on the page I can see that everything is working correctly within the view, the scene number is present in the textbox.
My controller action when this form submits is as follows:
[Authorize]
[HttpPost]
public ActionResult updateprogress(int EnrollmentID, CourseViewModel model)
{
Enrollment enrollment = db.enrollment.Find(EnrollmentID);
Mapper.Map(model, enrollment);
db.SaveChanges();
return null;
}
I'm using Automapper to map the change to the viewmodel back to the actual model, only a single field is to change in the viewmodel. This might not be the ideal way to do it, I'm still trying to work out how I should approach this.
My two issues are:
1 - The form does not appear to pass anything back to the controller when it submits. So the 'model' object is empty, null. This leads me to believe that what I thought I understood about what I was doing was wrong. Why is the updated field not being passed back to the controller?
2 - Is this the best method for updating the value of a single field in the viewmodel?
Thanks
You have a very complex model, the internal model binder is not going to know what to do with it because you have an IEnumerable of an object and you're editing(or hiding in this case) progress1 of the first Enrollment. You'll have to create a custom model binder.
What's happening on the view is it's storing this input tag of progress1 but when the controller gets it, it's not going to have any idea which Enrollment object it belongs to.
Try just passing in the first Enrollment to your view for editing.
I am trying to bind a complex data structure to my controller in spring mvc with javascript.
I have this ViewModel;
public class LibraryViewModel{
private String idLibrary;
private String nameLibrary;
private List<Box> listBox;
//Getters and setters
}
And this is the box's class:
List listBox;
public class Box{
private String idBox;
private List<String> booksNames;
//Getters and setters
}
What I want to do?
I want to do the form binding idLibrary and nameLibrary with a form in jsp
<form:form modelAttribute = "libraryVM" id="bestForm".../>
And listBox get a data injection like with a function made in JavaScript.
$('#bestForm').submit(function() {
completeListBoxInfo();
$('#organizacion').val(a);
});
But I allways get null mi List in mi controller but I get fine my idLibrary and nameLibrary attributes.
#RequestMapping("/save")
protected void guardar(#RequestParam("libraryFM") LibraryViewModel newLibrary) {
...
}
How can I bind the View Model object with the function result of completeListBoxInfo();
Kind regards.
I am trying to call a method inside a controller in MVC from a javascript action. The javascript action is supposed to invoke this method inside the controller and send some parameters to it.
My Javascript code looks like this:
location.href = '#Url.Content("~/Areas/MyArea/MyMethod/"+Model.MyId)';
My Method is defined as follows:
[HttpGet]
public ActionResult MyMethod(int? MyId)
{
doSomething(MyId);
return View("MyView");
}
However, when i debug the application, when the method is called the MyId parameter is passed as null and not as the current value of the MyId parameter in my model. What can I do to correctly send or retrieve this value? Thanks!
In your route definition I suppose that the parameter is called {id} and not {MyId}:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"MyArea_default",
"MyArea/{controller}/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
}
So try to be more consistent and adapt your controller action parameter name accordingly:
[HttpGet]
public ActionResult MyMethod(int? id)
{
doSomething(id);
return View("MyView");
}
Also you probably wanna use url helpers instead of hardcoding some url patterns in your javascript code:
window.location.href = '#Url.Action("MyMethod", "SomeControllerName", new { area = "MyArea", id = Model.MyId })';
The Url.Content helper is used to reference static resources in your site such as javascript, css and image files. For controller actions it's much better to use the Url.Action helper method.
I have to get values from a controller method in a view to write into some javascript. In web pages it is as simple as <%=functionName()%>. Is there a way to do this in MVC. I cannot use the model because the javascript has to be available on page load. Any insights appreciated.
Is there a way to do this in MVC
Yes, of course.
I cannot use the model because the javascript has to be available on page load.
Of course that you can use a view model, there's nothing that would prevent you from doing so. So you start by defining it:
public class MyViewModel
{
public string Foo { get; set; }
}
then have a controller action that will populate this view model and pass it the view:
public ActionResult Index()
{
var model = new MyViewModel();
model.Foo = "Hello World";
return View(model);
}
and finally have a strongly typed view to this view model in which:
#model MyViewModel
<script type="text/javascript">
$(function() {
var foo = #Html.Raw(Json.Encode(Model.Foo));
alert(foo);
});
</script>
But now let's suppose that you don't want to pollute your view with javascript but have it in a separate js file instead (which of course is the correct way).
You could embed the value somewhere in your DOM, for example using HTML5 data-* attributes:
<div id="foo" data-model="#Html.Raw(Html.AttributeEncode(Json.Encode(Model)))">
Click me to surprise you
</div>
and then in a separate javascript subscribe to the click event of this element and read the data-* attribute in which we have JSON serialized the entire view model:
$(function() {
$('#foo').click(function() {
var model = $(this).data('model');
alert(model.Foo);
});
});