I'm trying to update an image to my database, I defined as property model (bounded by database) the following:
public byte[] AvatarImage { get; set; }
then I created another property which store the value in the ViewModel:
public IFormFile AvatarImage { get; set; }
this steps are also described here in the doc.
Iside my form, I added the following html:
<div class="form-group text-center col-lg-12">
<img src="#Model.AvatarImage" class="avatar img-circle" alt="avatar" />
<h6>#Localizer["UploadNewAvatar"] ...</h6>
<input type="file" class="form-control" id="avatarUrl" asp-for="#Model.AvatarImages" />
</div>
when I submit the form the property AvatarImage is even null. But I don't understand why happen this, because all the other form properties are valorized correctly
Sounds like you are missing the form enctype.
Make sure you have:
<form enctype="multipart/form-data">
... inputs
<form>
Your <input type="file"> element assignment below seems to be wrong, because it uses #Model directive which outputs value of AvatarImages property (and the property is not exist in viewmodel class):
<input type="file" class="form-control" id="avatarUrl" asp-for="#Model.AvatarImages" />
The correct way is just using the property name like example below, because asp-for="PropertyName" is equivalent to model => model.PropertyName in HTML helper (assumed you have #model directive set to a viewmodel class):
<input type="file" class="form-control" asp-for="AvatarImage" />
Also don't forget to specify enctype="multipart/form-data" attribute in <form> tag helper:
<form asp-controller="ControllerName" asp-action="ActionName" method="post" enctype="multipart/form-data">
<!-- form contents here -->
</form>
Reference: Tag Helpers in forms in ASP.NET Core
First add enctype="multipart/form-data" to form ;
Then,check your #model, two situations :
1.Use Model directly, since the image is a byte array type, you need to convert the file type to byte[] during the submission process.
2.Or you could use ViewModel, and change the parameter type to viewmodel in the method.
Related
I need to obtain vaulue of an input using thymeleaf and spring but haven't been able to do so. Since I need that value in a lot of the methods in the controller I can't put that input inside of one of the forms.
I tried to use javascript to pass on the value to a hidden input in the forms, however since I'm using th:each I'm only getting the value of the first input.
I also tried adding a string to the model and then trying to access that string with #ModelAttribute, but it didn't workout either.
This is the html:
<tr th:each="pro:${productos}">
<td th:text="${pro.id}">id</td>
<!-- More code here omitted for brevity-->
<td>
<div>
<form th:action="#{|/actualizarMas/${pro.id}|}" method="post">
<button type="submit" id="mas">+</button>
</form>
<form th:action="#{|/actualizarMenos/${pro.id}|}" method="post">
<button type="submit" id="menos">-</button>
</form>
<input name="masomenos"/>
<form th:action="#{|/${pro.id}|}" method="post">
<button type="submit">Borrar</button>
</form>
</div>
</td>
</tr>
This is the controller:
#RequestMapping(value = "/actualizarMenos/{productosId}", method = RequestMethod.POST)
public String eliminarUno(#PathVariable int productosId, RedirectAttributes redirectAttributes, #RequestParam("masomenos") String masomenos) {
//Code here using that string omitted for brevity
return "redirect:/";
}
I need to access the input with the name "masomenos", if that is posible, how could I do it?, if not, what options do I have? besides creating inputs inside all the forms.
Thank you very much.
In my current application by using init binder-StringTrimmerEditor we are nullifying all the values which are empty from the view/templates. But now I want to remove one field(movielist) from being nullified as this particular field when I edit the form i.e., remove all the values in the movie-list and click save button controller is getting null value instated of empty string. I want it to be as empty String instead of null value.
How do I exclude the movielist from being nullified.
<form action="#" th:object="${CustomerForm}" th:action="#{customer/save}" method="post">
<input type="hidden" th:field="*{id}"/>
<textarea th:field="*{movieList}"></textarea>
<div class="modal-footer">
<input class="btn-submit" type="submit" value="Save"/>
</div>
</form>
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String.class, new StringTrimmerEditor(emptyAsnull:true));
}
You can look at this question
. You might have to set the allowed fields value for your databinder which will also solve a potential security concern.
I am using Tuple to pass two models inside the view like code given below.
#model Tuple<AdvanceSearchModel, List<SearchUserModel>>
<form role="search" method="post" action="/Public/AdvanceSearch">
<div class="form-group">
<label>Name</label>
<input name="FullNames" type="text" class="form-control" value=""/>
</div>
<div class="form-group">
<label>Product</label>
<input name="Products" type="text" class="form-control" value="" />
</div>
<div class="form-group">
<label>Location:</label>
<input name="Location" type="text" class="form-control" value="" />
</div>
<div class="form-group">
<label>State</label>
<input name="States" type="text" class="form-control" value="" />
</div>
<div class="form-group">
<label>Country</label>
<input name="Countries" type="text" class="form-control" value=""/>
</div>
</form>
All the name attributes inside inputs are of AdvanceSearchModel. How do I use tag helper such as asp-for when passing multiple model to the views containing one or multiple forms? Also how do I retain values of the form after submitting the form in above scenario?
As you can see in the source code of InputTagHelper
You can see it creates the name attribute based on the (lambda) expression in html-tag:asp-for.
what you need
You need a form name tag like this SearchUserModel[0].Location
Where:
SearchUserModel is the property name on the model which is in the controller method you post to
[0] is the index in the list
Location is the property on the iten in the list the SearchUserModel instance
My suggestion
Not to do
Extend the InputTagHelper and add a prefix option (which adds a prefex to the name).
Use a view model Not a tuple!
Create a partial view that only takes SearchUserModel + a prefix (like an int for which row in the list it is for example: usermodel[1])
In your view loop over the list and call the partial.
result
#model SearchUserModel
<input asp-for="Location" my-prefix="ListItem[#Model.Id]" class="form-control" />
Better longterm option
Make a HTML template on how SearchUserModel part of the form should look.
Do ajax call to get the data or put the data as json in your view. (or take step 3 from what not to do)
Generate the form with well structured javascript.
On submit Instead of submitting the form, parse the from to json and send this as json ajax call.
Why do i say this? It is easier to debug if you get weird databindings in your controller.
That said, option 1 is perfectly fine but it might lead to problems later, as it is very static template, you wont be able to add or remove rows easily.
References for proper html name tags for lists:
http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx
How does MVC 4 List Model Binding work?
When I submit this:
<form:form action='/controller.do' method='POST'>
<input type='text' value='test' name='myName" />
<input type='submit'/>
</form:form>
How can I retrieve the value of 'myName' in Spring 3 MVC Controller without using form tag?
If I understand your question correctly, you put some plain HTML <input> tags inside Spring MVC tag library's <form:form> tag.
Though it may work, it probably would be a better idea to use (depending on your situation) either plain HTML:
<form action='/controller.do' method='POST'>
<input type='text' value='' name='myName" />
<input type='submit'/>
</form>
or Spring MVC tags only:
<form:form action='/controller.do' method='POST' modelAttribute='fooModelAttribute'>
<form:input path='myName' />
<input type='submit'/>
</form>
You can retrieve the myName value by declaring the following parameter in your controller method:
#RequestParam("myName") String myNameVal
Alternatively, you can declare a class which has a myName field with a getter and setter (say, FooClass). And then you can declare the following parameter in the controller:
FooClass foo
This parameter may have an optional #ModelAttribute("fooModelAttribute") annotation.
See the Spring Reference for more details on #RequestParam, #ModelAttribute, and <form:form>.
I have something like this:
#Html.CheckBoxFor(model=>...)
<label>
#Html.DisplayFor(model=>...)
</label>
#Html.HiddenFor(model=>...)
But the final result in browser is:
1)Element
2)Hidden field
3)Label
I need to fix this because a library I use needs the label to be immediately after the Checkbox.
Why are you wrapping a <label> around a DisplayFor? Just use #Html.LabelFor.
Additionally. If you use the #Html.CheckBox.. helpers they will render a hidden field after the checkbox. There is a good reason for this, but requires a lengthy example.
What you probably want is an editor template. This should get you started:
#model Boolean
<input type="checkbox"
id="#ViewData.TemplateInfo.GetFullHtmlFieldId("")"
name="#ViewData.TemplateInfo.GetFullHtmlFieldName("")" />
The file for the code above is called "MyCheckbox" and is in Views/Shared/EditorTemplates
Model:
[UIHint("MyCheckbox")]
public bool MyProp { get; set; }
View:
#Html.EditorFor(x=> x.MyProp)
#Html.LabelFor(x=> x.MyProp)
Output:
<input type="checkbox" id="MyProp" name="MyProp">
<label for="MyProp">MyProp</label>