I have a file upload form to be submitted.And Below is the ViewModel and it's DataAnnotations. Upon the form submit, the ModelState is getting false. When checked for File property in the ViewModel, it is null. Despite I kept the enctype="multipart/form-data, I'm still getting null.
Could anyone please help me.
public class ExcelUploadViewModel
{
/// <summary>
/// Gets or Sets the FileName
/// </summary>
[Required(ErrorMessage = "FileName is required")]
public string FileName { get; set; }
[Required(ErrorMessage = "File is required")]
[DataType(DataType.Upload)]
public IFormFile File { get; set; }
}
Controller.cs
[HttpPost]
public async Task<IActionResult> UploadExcel(ExcelUploadViewModel excelUploadModel)
{
if (ModelState.IsValid)
{
// HttpResponseMessage response;
TransactionResultBase transactionResultBase = new TransactionResultBase();
IFormFile file = Request.Form.Files[0];
}
}
And FormUpload.cshtml
<div align="left">
<form id="uploadForm" enctype="multipart/form-data" name="uploadForm" asp-action="UploadExcel" method="post" >
<div class="form-group form-group-lg form-group-sm row " >
<div class="col-sm-12 col-md-10 col-lg-10 uploadDiv" style="display: flex !important">
<label asp-for="FileName" class="col-sm-12 col-md-10 col-lg-10" style="font-size: 15px; max-width: fit-content ">File Name :</label>
<input asp-for="FileName" class="form form-control fileName"
type="text"
name="fileName"
placeholder="Enter your file name"
id="fileName" />
<span asp-validation-for="FileName" class="text-danger"></span>
<input asp-for="File" required class="form-control file" type="file" placeholder="File Name" id="file" name="uploadFile" />
</div>
</div>
<small>Please upload .xls or .xlxs or json or xml formatted files only</small>
<div class="form-group form-group-lg form-group-sm row">
<div class="col-sm-12 col-md-10 col-lg-10">
<input type="submit" class="btn btn-primary" name="submit" id="fileUploadButton" value="Upload" />
<input type="reset" class="btn btn-Gray" name="result" id="resetButton" value="Reset" />
</div>
</div>
</form>
</div>
Tag helpers produce id and name attiribute according to the model. So dont use both tag helpers and name attiribute at the same time.
If you want to use tag helper asp-for is enough.If you want to use "name" attiribute then you should use it according to your model and property name. In this situation since you used name attiribute for file input name="uploadFile" your model cannot determine which property is that, so you should correct it name="File"
Be careful it changes if you are using viewmodel in the view.
Related
I am sending an id in my js code and I want to pass that variable to my controller. Any advice on how I can do that?
<input class="btn_confirm" type="submit" id={i}
onclick="id_click(this.id)" value="Delete" />
var id;
function id_click(clicked_id) {
id = clicked_id;
}
I tried different things but nothing worked out.
I tried as below:
Model:
public class ReceiveModel
{
public int Id { get; set; }
public string Name { get; set; }
public string SomeKey { get; set; }
}
View:
<div class="row">
<div class="col-md-4">
<form id="form" asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<input id="1" type="submit" value="Create" class="btn btn-primary" />
</div>
<div class="form-group">
<input id="2" type="submit" value="Create" class="btn btn-primary" />
</div>
<div class="form-group">
<input id="3" type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script>
$("input[type='submit']").click(function ()
{
var tempid = this.id
var tmpInput = $("<input type='text' name='SomeKey' hidden/>");
tmpInput.attr("value", tempid );
var form = $("#form")
form.append(tmpInput)
form.submit()
})
</script>
Result:
You can lookup API requests. If you want to send one parameter as a primitive type (string, integer, etc.) you can use query strings in your API calls. For example, let's assume you have an API endpoint like this: localhost:5000/api/YourController. You can send params via API get calls like this localhost:5000/api/YourController?yourParam=<param-value>. In this example your API call type is GET.
If you want to send complex types (like classes, objects) to your controller you can lookup POST API requests.
You can find more details in this documentation.
I am trying to use client side validation and its not working. My model is:
[Required]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
my layout used by the view has:
<script src="~/js/jquery-3.6.0.min.js" type="text/javascript"></script>
<script src="~/js/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>
<script src="~/js/jquery.validate.js" type="text/javascript"></script>
my view has:
<div class="form-group">
<label asp-for="Email"></label>
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
when I check the form html in the browser it shows:
<div class="form-group">
<label for="Email">Email</label>
<input class="form-control" type="email" data-val="true" data-val-required="The Email field is required." id="Email" name="Email" value="">
<span class="text-danger field-validation-valid" data-valmsg-for="Email" data-valmsg-replace="true"></span>
</div>
but when I click the submit button, the form is been posted to the server which means the client side validation is not working.
For some reasons you have to add asp-validation-summary just below form tag
<form id="myForm">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
.....
.....
</form>
The solution is that you should load the jquery.validate script before the unobtrusive script. Found the answer here
Uncaught TypeError: Cannot set property 'unobtrusive' of undefined
Hi I am working with spring MVC and thymeleaf and I am not able to update data from my controller as I have following code.The main problem I am facing is that my put method is not getting called.
#GetMapping("/{id}/edit")
public String editUser(#PathVariable("id") int id, Model model) {
logger.info("++++++++++++[edit User]\n\n" + userService.findById(id));
model.addAttribute("user", userService.findById(id));
return "user/edit";
}
#PutMapping("/{id}/edit")
public String updateUser(#PathVariable("id") int id, #ModelAttribute("user") User user, Model model) {
logger.info("\n\n+++++++++++++++++inside Update");
User toUpdate = userService.findById(user.getId());
user.setUserName(user.getUserName() != null ? user.getUserName() : toUpdate.getUserName());
user.setName(user.getName() != null ? user.getName() : toUpdate.getName());
logger.info(user.toString());
userService.updateUser(user);
model.addAttribute("user", userService.findById(user.getId()));
return "redirect:/user/" + id;
}
and my html page
<form action="#" th:action="#{/user/__${user.id}__}" method="put"
th:object="${user}">
<div class="form-group">
<label for="txtUserName">User-name</label> <input
class="form-control" id="txtUserName" placeholder="User Name"
th:feild="${user.userName}" />
</div>
<div class="form-group">
<label for="txtName">First Name</label> <input
class="form-control" id="txtName" placeholder="Full Name"
th:feild="${user.name}" />
</div>
<div class="form-group">
<label for="calDob">Date of Birth</label> <input
class="form-control" id="calDob" placeholder="dd/MM/yyyy" />
</div>
<button type="submit" th:method="put" class="btn btn-success">Update</button>
<a href="#" th:href="#{/user/__${user.id}__}"
class="btn btn-primary">Cancel</a> <a th:method="delete"
href="javascript:deleteUser('${user.id}');" class="btn btn-danger">Delete</a>
</form>
any help will be usefull thanks
PUT is not a valid argument for method attibute of the form tag. See HTML specification.
Valid methods are GET and POST. And as it's not a REST API, you can use POST method to update.
So just update your mapping from:
#PutMapping("/{id}/edit")
to
#PostMapping("/{id}/edit")
And form tag to:
<form action="#" th:action="#{/user/__${user.id}__}/edit" method="post" th:object="${user}">
I want to post a list of strings to my controller.
But it always only take the first selected value.
my thymeleaf html form:
<form action="/add" method="post">
<div class="form-group">
<label for="roleId">ID</label> <input type="text" class="form-control" id="roleId" name="id" required="required" />
</div>
<div class="form-group">
<label for="rolePrivileges">Privileges</label>
<select class="form-control" id="rolePrivileges" name="privileges" multiple="multiple" size="10" required="required">
<option th:each="type : ${privilegesList}" th:value="${type}" th:text="${type}">Privilege</option>
</select>
</div>
<button type="submit" class="btn btn-default">Create</button>
</form>
my controller:
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String addSomething(Model model, #ModelAttribute("id") String id,
#ModelAttribute("privileges") List<String> privileges) {
// add something with a service
return "redirect:/roles";
}
I think you have to Annotate the privilges with
#RequestParam("privileges")
It is not a ModelAttribute but you receive it from the request
Edit: two SO threads to better understand the difference between #RequestParam and #ModelAttribute.
My form code is not generating correct HTML. Here's my code.
Here's the form code:
#using (Html.BeginForm("SendEmail", "PropertyDetails", FormMethod.Post))
{
<fieldset>
<div class="left">
<label for="Name">Your Name</label>
<input type="text" required name="Name" />
<label for="Phone">Your Phone Number</label>
<input type="text" required name="Phone" />
<label for="Email">Your Email</label>
<input type="email" class="text" required name="Email" />
</div>
<div class="right">
<label for="Message">Your Message</label>
<textarea name="Message">
</textarea>
<input type="submit" name="submit" value="send" />
<div class="clear"></div>
</div>
<div class="clear"></div>
</fieldset>
}
Here's my Controller. I have a breakpoint on the first line of the SendMail message which isn't being hit:
public class PropertyDetailsController : Controller
{
[HttpPost]
public ActionResult SendEmail(EmailData email)
{
if (ModelState.IsValid) // BREAKPOINT ON THIS LINE ISN'T BEING HIT
{
etc.
Here's the class that should get populated with the form data and passed into the method (I'm not doing this myself. I assume it's happening automatically under the covers).
public class EmailData
{
private string _name;
private string _email;
private string _phone;
private string _message;
[Required]
[StringLength(50, MinimumLength = 1)]
public string Name
{
get { return _name; }
set { _name = value == null ? string.Empty : value.Trim(); }
}
[Required]
[RegularExpression(RegEx.Email, ErrorMessage = "Invalid e-mail address.")]
public string Email
{
get { return _email; }
set { _email = value == null ? string.Empty : value.Trim(); }
}
public string Phone
{
get { return _phone; }
set { _phone = value == null ? string.Empty : HtmlHelper.StripIllegalXmlChars(value.Trim()); }
}
[StringLength(500, MinimumLength = 1)]
public string Message
{
get { return _message; }
set { _message = value == null ? string.Empty : HtmlHelper.StripIllegalXmlChars(value.Trim()); }
}
}
Here's the HTML that's being generated:
<form action="" method="post">
<fieldset>
<div class="left">
<label for="Name">Your Name</label>
<input type="text" required name="Name" />
<label for="Phone">Your Phone Number</label>
<input type="text" required name="Phone" />
<label for="Email">Your Email</label>
<input type="email" class="text" required name="Email" />
</div>
<div class="right">
<label for="Message">Your Message</label>
<textarea name="Message">
</textarea>
<input type="submit" name="submit" value="send" />
<div class="clear"></div>
</div>
<div class="clear"></div>
</fieldset>
</form>
Any ideas why the action is empty?
Change your <form> declaration to this:
<% using (Html.BeginForm("SendEmail", "[Controller]")) { %>
<!-- Form data -->
<% } %>
Where [Controller] is the name of your Controller minus "Controller". In other words, if the controller name is HomeController, you would use "Home".
Try changing the form declaration within your view to this (using Razor syntax):
#using (this.Html.BeginForm("SendEmail", "[your controller name]", FormMethod.Post))
{
[form HTML]
}
The using statement will ensure that your form is closed correctly.
Also the HtmlHelper.BeginForm extension method is flexible enough that it generates the URI for the action based on the routes defined in your application's RouteCollection, such that if your routes change the form does not need to be updated; the change in URI is handled gracefully and automatically.
You need to add an action to your form
<form action="/SendEmail/" method="post">
But really this should be done using the MVC3 BeginForm helper.
You need to have your HTML rendered by a controller. So put your HTML in a View called "SendEmail" and write a controller action with an [HttpGet] attribute.
Call the Action "SendEmail" and in it just do return View().
Like this
[HttpGet]
public ActionResult SendEmail()
{
return View();
}
That will cause the BeginForm to render the action="" properly.
Then once that's working you are going to have a problem when you do post the data back because the input fields aren't bound to you model. You need to add #model yournamespace.EmailData to the very top of your View and then you need to change your inputs to bind to the model properties.
I've no idea how good this link is but it's the first one I found that looks like it might guide you through a similar process http://geekswithblogs.net/WinAZ/archive/2010/10/30/an-mvc-3-contact-form.aspx