Upload file with Boostrap Modal on Asp.net core 2.1 - ajax

I want to upload a file and send to email. But I don't see how to do this with Bootsrap Modal.
If you want any other information, tell me.
I would like to send the attached file by email then also integrate it in my database and be able to download it.
/[...]/ ==> Code that I didn't add, not useful.
Edit : Otherwise how to do with Ajax ?
My View :
<form name="contact" method="post" asp-action="Validation">
#if (ViewBag.Alert != null && ViewBag.Alert != "")
{
<div class="alert role="alert">
#ViewBag.Alert
</div>
}
<div class="details">
<h3 class="title">Demande</h3>
<label for="card">Type *</label>
<select required onchange="contact()" class=" form-control" disabled="true" name="type" value="#ViewBag.Form.Type">
<option value="1">Choose 1</option>
<option value="2">Choose 2</option>
</select>
<label for="card">Origine *</label>
<select required class="form-control" name="origine" value="#ViewBag.Form.Origine">
<option value="1">Origine 1</option>
<option value="2">Origine 2</option>
<option value="3">Origine 3</option>
</select>
/*[...]*/
<input type="hidden" name="Id" value="#ViewBag.Form.Id" />
<input type="hidden" name="Price" value="#ViewBag.Form.Price" />
/*[...]*/
<textarea class="form-control" name="Response" placeholder="Response..."></textarea>
<button required class="btn" onclick="modal_response()" data-whatever="getbootstrap" data-toggle="modal" data-target="#modal_contact" type="button">Response</button>
<label for="card" class="right">Response send</label><br />
<button required class="btn_second" onclick="modal_save()" data-whatever="getbootstrap" data-toggle="modal" data-target="#modal_contact_save" type="button">Save</button>
<label for="card-holder" class="right">Save Ok!</label>
/*[...]*/
<div class="form-row">
<button class="btn-primary" onclick="form_confirmation()" type="submit">Save All</button>
<button class="btn-secondary" type="reset" onclick="location.href = '#Url.Action("List", "Control", new { id = ViewBag.Id })';">Close</button>
</div>
</div>
</form>
/* When I click on "Response" a new window open */
<div class="modal fade" id="modal_contact" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog" role="document">
<h5 class="modal-title" id="modal_label">Send email to : #ViewBag.Form.Name</h5>
<button type="button" class="close" data-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="modal_contact_form" enctype = "multipart/form-data" method="post" action="#Url.Action("Modal_contact", "Control")">
<div class="form-group">
<input type="file" name="file" accept="application/pdf" /><br /><br />
<textarea class="form-control" name="Description" required placeholder="Content">#ViewBag.Response</textarea>
</div>
<input type="hidden" name="Id" value="ID" hidden />
<input type="hidden" name="Price" value="#ViewBag.Form.Price" hidden />
<input type="hidden" name="Type" value="#ViewBag.Form.Type" hidden />
/*[...]*/
<input type="submit" hidden />
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" data-dismiss="modal" onclick="$('#modal_contact_form').submit();" class="btn-primary">Send Email</button>
</div>
</div>
My Controller :
public class MyController : BaseEntity
{
[Required]
public string Id { get; set; }
public string Price { get; set; }
public string Type { get; set; }
/*[...]*/
/* For File I don't know if it's good?? */
public IformFile File { get; set; }
}
My Model :
public ActionResult Modal_contact(MyController model)
{
/* How to retrieve file ?? */
bool ok = false;
OtherController OC = new OtherController();
/*[...]*/
if (ModelState.IsValid)
{
OC = othercontrollerRepository.Find(model.Id);
OC.Email = this.Session_get("Email");
OC.Description = "";
model.Email = this.Session_get("Email");
model.Status = "1";
model.View = "response";
/*[...]*/
if (mycontrollerRepository.Add(model) && othercontrollerRepository.Update(OC))
{
/* How to send file to email and save file to folder in my project to add in my database ? */
MailManager mail = new MailManager();
Modele modele = new Modele();
modele= modeleRepository.Find("response");
ok = mail.send(modele.Objet, model.Description, OC.Email);
}
return Json(new { Json_result = ok, Redirect = "" });
}
return Json(new { Json_result = false, Redirect = "" });
}
I found my error :
Form before <div>

I tried your code and reproduced your issue. I noticed that you named the IFormFile object as File.
public IFormFile File { get; set; }
But input file you are getting is named file.
<input type="file" name="file" accept="application/pdf"/><br /><br />
Asp.net core model binding will bind the property according to the input name. This is the reason why you couldn't get the IFormFile value in controller.
To solve this issue, you should change the name of the input to File so that they could match each other.
Like below:
<input type="file" name="File" accept="application/pdf"/><br /><br />
Result:

Related

Model attribute inconsistent after form submission

I'm still trying to figure out what's happening on the backend here. Working with Spring Boot/Thymeleaf. I have a form template that updates a model attribute object on save. I'm trying to use the updated values on the backend, however it's inconsistent among my functions and I'm not sure why.
Thymeleaf template
<div layout:fragment="content" class="container">
<form action="#" th:action="#{/utility/exportbadges}" th:object="${badgeExport}" method="post">
<div class="form-group col-md-6">
<label class="col-form-label-sm">Badge type</label>
<select th:field="*{type}" class="form-control">
<option th:each="badgeType : ${T(org.myorg.myproject.model.badge.BadgeType).values()}"
th:value="${badgeType}"
th:text="${badgeType}">
</option>
</select>
</div>
<div class="form-group col-md-3">
<label class="col-form-label-sm">Use background?</label>
<input type="checkbox" th:field="*{background}" class="form-control">
</div>
<div class="form-group col-md-3">
<label class="col-form-label-sm">Mark preprinted?</label>
<input type="checkbox" th:field="*{preprinted}" class="form-control">
</div>
<div class="form-group col-md-3">
<label class="col-form-label-sm">Save to path (/tmp default):</label>
<input type="text" th:field="*{saveDir}" class="form-control" placeholder="/tmp">
</div>
<div class="form-group col-md-12 mt-2">
<div class="col-sm-10">
<input class="btn btn-primary" id="save" type="submit" value="Export" />
<input class="btn btn-secondary" type="reset" value="Reset" />
</div>
</div>
</form>
</div>
#RequestMapping(value = "/utility/exportbadges")
public String exportBadges(Model model) {
final BadgeExport badgeExport = new BadgeExport();
model.addAttribute("badgeExport", badgeExport);
return "utility/exportbadges";
}
POST method. The object is correct in this function. Any field that's edited in the form above reflects in this function. However, on redirect, the object is as if it only has default instantiation/has been unedited.
#RequestMapping(value = "/utility/exportbadges", method = RequestMethod.POST)
public String exportBadgeFlow(Model model,
#ModelAttribute("badgeExport") final BadgeExport badgeExport) {
log.info("BadgeExport badge type: {}", badgeExport.getType());
log.info("BadgeExport save dir pre export: {}", badgeExport.getSaveDir());
switch(badgeExport.getType()) {
case "Attendee":
log.error("Attendee export not yet implemented");
break;
case "Vip":
return "redirect:exportbadges/vip-badges.pdf";
case "Specialty":
return "redirect:exportbadges/specialty-badges.pdf";
case "Staff":
return "redirect:exportbadges/staff-badges.pdf";
case "Guest":
return "redirect:exportbadges/guest-badges.pdf";
}
return "redirect:exportbadges";
}
Redirect function. Badge type will be null and saveDir will be /tmp as default instead of updated value in form.
#RequestMapping(value = "/utility/exportbadges/vip-badges.pdf")
public ResponseEntity<String> getAllVipBadgePdf(#ModelAttribute("badgeExport") final BadgeExport badgeExport) throws IOException {
log.info("BadgeExport badge type: {}", badgeExport.getType());
log.info("BadgeExport save dir during export: {}", badgeExport.getSaveDir());
}

How can I store records in a list request from an HttpPost

How can I store records in a list from an HttpPost request that sends an object
I want to store each record that it processes again from the view
Take the _students object and send it to a list:
List dbTempStudentList
To work locally with data and not depend on a database
[HttpPost]public ActionResult Create(Student _student)
{
return View("");
}
public class Student
{
public int StudentID { get; set; }
public string StudentName { get; set; }
public string StudentLastName { get; set; }
public string Creditbalance { get; set; }
public string CurrentBalance { get; set; }
}
My View Create
<h2>Create</h2>
<h4>Student</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="StudentID" class="control-label"></label>
<input asp-for="StudentID" class="form-control" />
<span asp-validation-for="StudentID" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="StudentName" class="control-label"></label>
<input asp-for="StudentName" class="form-control" />
<span asp-validation-for="StudentName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="StudentLastName" class="control-label"></label>
<input asp-for="StudentLastName" class="form-control" />
<span asp-validation-for="StudentLastName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Creditbalance" class="control-label"></label>
<input asp-for="Creditbalance" class="form-control" />
<span asp-validation-for="Creditbalance" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="CurrentBalance" class="control-label"></label>
<input asp-for="CurrentBalance" class="form-control" />
<span asp-validation-for="CurrentBalance" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
</div>
</div>
[HttpPost]
public ActionResult Create(Student _student)
{
var list = (List<Student>)Session["studentList"];
//this is for first time
if(list==null||list.Count()==0) list = new List<Student>();
list.Add(_student);
Session["studentList"]=list;
return View();
}

Vue.js Asp.NET core Form validation

I am currently learning vuejs with asp .net core right now.
I am doing some form validation and adding some error messages.
The error messages are from the Server side here is my sample code:
[HttpPost]
public async Task<IActionResult> AddUser([FromBody] UserModel user)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (_context.Users.Any(u => u.UserName == user.UserName))
{
ModelState.AddModelError("UserName", "Username is already in used");
return BadRequest(ModelState);
}
try
{
var userDto = new User
{
FirstName = user.FirstName,
LastName = user.LastName,
Password = user.Password,
UserName = user.UserName
};
_context.Users.Add(userDto);
await _context.SaveChangesAsync();
}
catch(Exception e)
{
ModelState.AddModelError("Saving Error", string.Format("Error in saving user. \nDetails:\n {0}", e.Message));
return BadRequest(ModelState);
}
return Ok();
}
And in the view:
<form v-on:submit.prevent="SaveUser()">
<div class="form-group">
<label for="userName">User Name</label>
<input class="form-control" type="text" id="userName" placeholder="Username" v-model="userName" required :disabled="isEditMode" />
</div>
<div class="form-group">
<label for="userName">First Name</label>
<input class="form-control" type="text" id="firstName" placeholder="First Name" v-model="firstName" required />
</div>
<div class="form-group">
<label for="userName">Last Name</label>
<input class="form-control" type="text" id="lastName" placeholder="Lastname" v-model="lastName" required />
</div>
<div v-if="!isEditMode">
<div class="form-group">
<label for="userName">Password</label>
<input class="form-control" type="password" id="password" placeholder="Password" v-model="password" required />
</div>
</div>
<!--TODO: Distribute to each control-->
<div v-if="hasError">
<ul v-for="error in errors">
<li style="color: red;" v-for="detail in error">{{detail}}</li>
</ul>
</div>
<button type="submit" class="btn btn-primary">Save</button>
<button type="button" #click="backToList()" class="btn btn-danger">Cancel</button>
</form>
Basically I am doing the validations from the server-side.
Currently the error messages are displayed below the controls
And I need to distribute all the error message inline with the inputs.
Can you help me with this?
Thanks in advance.

ASP.NET Core model binding

I'm trying to bind an edit action to a model which doesn't work. Here below the controller:
[Route("[controller]/[action]")]
public class CustomerController : Controller
{
private readonly IUnitOfWork _unitOfWork;
public CustomerController(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
[HttpGet("{_customerCode}")]
public IActionResult Edit(int _customerCode)
{
var customer = _unitOfWork.Customers.getCustomerByCode(_customerCode);
var customerDTO = Mapper.Map<CustomerModelDTO>(customer);
return View(customerDTO);
}
[HttpPost]
public IActionResult Edit(CustomerModelDTO model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var _customer = _unitOfWork.Customers.getCustomerByCode(model.CustomerCode);
if (_customer==null)
{
return NotFound();
}
Mapper.Map(model, _customer);
_unitOfWork.Complete();
return RedirectToAction("Detail", new { customerCode = _customer.CustomerCode });
}
}
And here is the view I am using:
#model Almiz.Dtos.CustomerModelDTO
<form asp-action="Edit" method="post">
<div class="form-horizontal">
<h4>CustomerModelDTO</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="CustomerCode" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="CustomerCode" class="form-control" />
<span asp-validation-for="CustomerCode" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="FirstName" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="FirstName" class="form-control" />
<span asp-validation-for="FirstName" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="MiddleName" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="MiddleName" class="form-control" />
<span asp-validation-for="MiddleName" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="LastName" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="LastName" class="form-control" />
<span asp-validation-for="LastName" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="Telephone" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Telephone" class="form-control" />
<span asp-validation-for="Telephone" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="Mobile" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Mobile" class="form-control" />
<span asp-validation-for="Mobile" class="text-danger" />
</div>
</div>
<div class="form-group">
<label asp-for="Email" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</form>
<div>
<a asp-action="Index">Back to Index</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
When I call the view and with the ID http://localhost:65001/Customer/Edit/1001, I get the all the information. However when I edit it and post the edited form I get resource not found error. Please help. Here below the model:
public class CustomerModelDTO
{
public int CustomerCode { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public double Telephone { get; set; }
public double Mobile { get; set; }
public string Email { get; set; }
}
I got it working. Here below the change.
[HttpPost("{customerCode}")]
public IActionResult Edit(int customerCode, CustomerModelDTO data)

How tell the view an error has occured from controller? (Spring MVC)

How can I say trigger error/validation messages in the view from the controller in a better way? Currently, I do this by sending boolean attributes. For example, in creating a product, I have two possible errors. Invalid format of UPC of a product, or duplicate upc. I also have a validati
#RequestMapping("/createProduct")
public String createProduct(Model model, #RequestParam(value = "name") String name,
#RequestParam(value = "upc") String upc, #RequestParam(value = "category") String categoryName,
#RequestParam(value = "description") String description, #RequestParam(value = "price") BigDecimal price,
#RequestParam(value = "stock") int stock){
model.addAttribute("activeTab", 3);
if(Validator.invalidUpcFormat(upc)){
model.addAttribute("invalidFormat", true); //trigger for invalid format
return "management";
}
Category category = productService.getCategory(categoryName);
Product product = new Product(upc, category, name, description, price);
InventoryProduct inventoryProduct = new InventoryProduct(product, stock);
try {
managerService.add(inventoryProduct);
model.addAttribute("productCreated", true);
} catch (DuplicateProductException e) {
model.addAttribute("upc", upc);
model.addAttribute("duplicateProduct", true); // trigger for duplicate product
}
return "management";
}
And here is my view:
<div id="menu3"
class="tab-pane fade <c:if test="${activeTab == 3}">in active</c:if>">
<div class="container-fluid" style="padding: 2%;">
<div class="row">
<div class="col-md-12"
style="padding-left: 15%; padding-right: 15%;">
<c:if test="${productCreated}">
<div class="alert alert-success fade in">
<a href="#" class="close" data-dismiss="alert"
aria-label="close">×</a> <strong>Success!</strong>
Product has been created!
</div>
</c:if>
<c:if test="${duplicateProduct}">
<div class="alert alert-warning fade in">
<a href="#" class="close" data-dismiss="alert"
aria-label="close">×</a> <strong>Oh no!</strong>
Product with the UPC ${upc} already exists!
</div>
</c:if>
<c:if test="${invalidFormat}">
<div class="alert alert-warning fade in">
<a href="#" class="close" data-dismiss="alert"
aria-label="close">×</a> <strong>Oops!</strong>
Invalid UPC format!
</div>
</c:if>
<form
action="${pageContext.request.contextPath}/manager/createProduct"
method="post">
<div class="form-group">
<label for="Name">Name </label> <input type="text" name="name"
class="form-control" required />
</div>
<div class="form-group">
<label for="UPC">UPC </label> <input type="number" name="upc"
class="form-control" required />
</div>
<div class="form-group">
<div class="form-group">
<label for="category">Category</label> <select
class="form-control" name="category" required>
<option selected disabled value="">SELECT CATEGORY</option>
<c:forEach items="${categories}" var="item">
<option>${item.getName()}</option>
</c:forEach>
</select>
</div>
</div>
<div class="form-group">
<label for="description">Description</label>
<textarea class="form-control" rows="5" name="description"></textarea>
</div>
<div class="form-group">
<label for="price">Price </label> <input type="number"
name="price" class="form-control" required />
</div>
<div class="form-group">
<label for="stock">Stock </label> <input type="number"
name="stock" class="form-control" required />
</div>
<button type="submit" class="btn btn-primary">Add
product</button>
</form>
</div>
</div>
</div>
</div>
Is there a better of doing this other than sending boolean triggers?
You could use Spring BindingResult. This is typical filled with the result of Binding and Validation results. But you can also add errors by hand.
But first you need to refactor your code, so that you use an single command/form-backing object instead of all the #Param values
public class CreateProductCommand {
private String name;
private String upc;
private String categoryName;
.... //other fields
public CreateProductCommand (){} //parameter less conturctor
Getter+Setter
}
Controller
#RequestMapping("/createProduct")
public ModelAndView createProduct(CreateProductCommand createProductCommand, BindingResult bindingResult) //Binding result must be the parameter direct next to the object that should been validated!!!
{
if (someustomValidationForUcpFail()) {
bindingResult.rejectValue("upc", //the field name of the invalid field
"error.Message.Key",
"Default Error Message");
}
if (bindingResult.hasErrors()) {
ModelMap model = new ModelMap();
model.add("createProductCommand", createProductCommand);
return new ModelAndView("createForm", model)
} else {
Product product = ...
return new ModelAndView("showProduct", "product", product)
}
}
jsp:
You need to use springs form and input tag:
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:springForm="http://www.springframework.org/tags/form"
version="2.0">
....
<springForm:form action="<c:url value="/manager/createProduct">" method="POST" modelAttribute="createProductCommand">
<springForm:input path="name"/> <form:errors path="name" />
<springForm:input path="ucp"/> <form:errors path="ucp" />
....
</springForm:form>
....

Resources