Can not upload file/image - asp.net-mvc

I am working on a simple form where user will enter some data and select a file to upload.
But i can not get this working..
For some reason when I click save, the file does not go to the controller.
Here is some code.
#using (Ajax.BeginForm("Add", "Category", null, new AjaxOptions
{
UpdateTargetId = "upload-message",
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "uploadSuccess"
}, new { id = "AddCategoryForm", enctype = "multipart/form-data" }))
{
<div class="editorLabel">
#Html.LabelFor(m=>m.CategoryName)
</div>
<div class="editorText">
#Html.TextBoxFor(m=>m.CategoryName)
</div>
<div class="editorLabel">
#Html.LabelFor(m => m.Description)
</div>
<div class="editorText">
#Html.TextAreaFor(m => m.Description)
</div>
<div class="editorLabel">
#Html.LabelFor(m => m.IconPath)
</div>
<div class="editorText">
<input type="file" id="file" name="file" />
</div>
<div class="editorLabel">
#Html.LabelFor(m => m.IsActive)
</div>
<div class="editorText">
#Html.CheckBoxFor(m=>m.IsActive)
</div>
<p>
<input type="submit" id="submit" value="Save" />
</p>
}
Controller:
[HttpPost]
public ActionResult Add(HttpPostedFileBase file,CategoryViewModel model)
{
if (ModelState.IsValid)
{
System.IO.FileInfo info = new FileInfo(file.FileName);
string ext = info.Extension;
//other code
}
}
Here in the controller, file is always null.
Where am I doing wrong??

First swapping parameters of your controller to have it as follows:
[HttpPost]
public ActionResult Add(CategoryViewModel model, HttpPostedFileBase file)
For example.
If this won't work for some reason, make the file you uploading part of your model (CategoryViewModel) and have controller signature as follows:
[HttpPost]
public ActionResult Add(CategoryViewModel model)
For example. That way file will be returned as part of the model and you will extract it as one of model's properties. This will work (it worked for me).
Hope this helps.

Related

Multiple forms in one view page

I'm working on an application that handles employee's profile.
I have 3 forms (all in the same controller) in a single view page, but it only saves the 1st form. And when i save the 2nd form, it clears the values of the 1st and 3rd form.
Here is my code:
Views/EMPs/Index:
#using (Html.BeginForm("Edit", "EMPs", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
<div class="pull-right">
<input type="submit" value="Update" name="personalsubmit" class="btn btn-success" />
</div>
</div>
}
#{ Html.RenderAction("Index", "EMP_REFERENCE", new { id = Model.eMP.lineno });}
#using (Html.BeginForm("Edit", "EMPs", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
<div class="pull-right">
<input type="submit" value="Update" name="jobsubmit" class="btn btn-success" />
</div>
</div>
}
#{ Html.RenderAction("Index", "EMP_BENEFITS", new { id = Model.eMP.lineno });}
#using (Html.BeginForm("Edit", "EMPs", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
<div class="pull-right">
<input type="submit" value="Update" name="otherssubmit" class="btn btn-success" />
</div>
</div>
}
EMPsController
public ActionResult Edit([Bind(Include = "lineno,EMPNO,IDNO..")] EMP eMP)
{
if (ModelState.IsValid)
{
if (Request.Form["personalsubmit"] != null)
{
db.Entry(eMP).State = EntityState.Modified;
db.SaveChanges();
}
if (Request.Form["jobsubmit"] != null)
{
db.Entry(eMP).State = EntityState.Modified;
db.SaveChanges();
}
if (Request.Form["otherssubmit"] != null)
{
db.Entry(eMP).State = EntityState.Modified;
db.SaveChanges();
}
return Redirect(Request.UrlReferrer.PathAndQuery);
}
return View(eMP);
}
I couldn't put them all in one form, because i used an ajax beginForm between them for another crud method. Since I've read that nested forms are not recommended.
Is there a way to save one form without it clearing the values of the other forms?
Is there a way to save one form without it clearing the values of the other forms?
You could simply use ajax.beginform for each of those forms;
How to use Simple Ajax Beginform in Asp.net MVC 4?
Or you could make your own ajax implementation
https://www.c-sharpcorner.com/blogs/using-ajax-in-asp-net-mvc
Or you could just go ahead and bind everything on your model;
// don't need to specify which properties to bind, all of the available properties in your view will be bound to the model on POST
public ActionResult Edit(EMP eMP)
{
if(eMP.FirstName!=null ...){
// ... do some checking depending on what values are submitted
}
// save profile here
// when you return the view
return View(eMP);
}
but for this method you need to only have 1 form for Personal,Job, and Others.
#{ Html.RenderAction("Index", "EMP_REFERENCE", new { id = Model.eMP.lineno });}
#{ Html.RenderAction("Index", "EMP_BENEFITS", new { id = Model.eMP.lineno });}
#using (Html.BeginForm("Edit", "EMPs", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<!--put all your employee input fields here-->
<div class="form-group">
<div class="pull-right">
<input type="submit" value="Update" name="submit" class="btn btn-success" />
</div>
</div>
<!--put all your job input fields here-->
<div class="form-group">
<div class="pull-right">
<input type="submit" value="Update" name="submit" class="btn btn-success" />
</div>
</div>
<!--put all your others input fields here-->
<div class="form-group">
<div class="pull-right">
<input type="submit" value="Update" name="submit" class="btn btn-success" />
</div>
</div>
}

How to validate a duplicate post request from a form in MVC

I am having an form which insert a record whenever a post request is made,but the problem is that if someone clicks submit button more than 1 times than duplicate post request are made and at the end same records are getting inserted. I dont want to check that the record is already present or not because the record would be different always. I tried using ValidateAntiForgeryToken filter in controller but it is failing to validate the requests, Below is my View Code.
#using (Html.BeginForm("Create", "Home",FormMethod.Post,new { onkeydown = "return event.keyCode!=13" }))
{
#Html.AntiForgeryToken()
<div class="right-col">
#Html.TextBoxFor(model => model.Name, new { placeholder = "Name", #class = "small-box" })
</div>
<div class="left-col">Email Id :</div>
<div class="right-col">
#Html.TextBoxFor(model => model.EmailId, new { placeholder = "Email Id", #class = "small-box",id="resumeemailid" })
#Html.ValidationMessageFor(model => model.EmailId)
</div>
<div class="left-col">Address :</div>
<div class="right-col">
#Html.TextAreaFor(model => model.Address, new { placeholder = "Address", #class = "small-box" })
</div>
<div class="buttons resume-threebutton">
<input type="submit" id="register-button" class="gradient-btn" value="#T("Account.Passport.Register.Button.Upload", "Upload")" name="Command" />
<input type="submit" id="register-button" class="gradient-btn" value="#T("Account.Passport.Button.UploadandAdd", "Upload And Add New")" name="Command" />
<input type="button" id="register-button" class="gradient-btn" value="#T("Account.Passport.Register.Button.Cancel", "cancel")" name="register-button" onclick="location.href='#Url.Action("SelectTemplate", "CustomerTemplate")'" />
</div>
}
and below is my controller Post method
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ProductModel model)
{
//To do add the product here...
}

MVC parial view going to get method rather than post on submit

I have a partial view which shows a search box with a couple of options
model PatientSearchViewModel
#using (Html.BeginForm("Index", "Patient", FormMethod.Post, new { #class = "form-inline" }))
{
<form class="form-inline">
<label style="padding-right:20px;">Search for a patient</label>
#Html.EditorFor(model => model.SearchText, new { htmlAttributes = new { #class = "form-control", placeholder = "Search...", autocomplete = "off" } })
<div class="checkbox">
<div class="checkbox" style="padding-left:20px; padding-right:20px;">
<label>#Html.EditorFor(model => model.ShowOnlyOpenClients) Show only open clients</label>
</div>
</div>
<button type='submit' name='seach' id='search-btn' class="btn btn-primary"><i class="fa fa-search"></i>Search</button>
</form>
}
When the submit button is hit I want it to go to my method below with the search content already complete, however instead it goes to the HttpGet method which is bringing back a null for the PatientSearchViewModel.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(PatientSearchViewModel patient)
{
PatientSearchViewModel patientVM = GetSearchResults(patient);
return View(patientVM);
}
Can anyone explain how I can get this to work?
I have executed the code snippet you pasted here and found that
As you are making the use of the [ValidateAntiForgeryToken]
attribute so you need to add the #Html.AntiForgeryToken(); this
statement in your partial view inside the
#using(Html.BeginForm()){ } block.
One more thing make sure that your action method will be inside the
PatientController.
For your reference (this is my code)
#model WebApplication.Models.PatientSearchViewModel
#using (Html.BeginForm("Index", "Patient", FormMethod.Post, new { #class = "form-inline" }))
{
#Html.AntiForgeryToken();
<label style="padding-right:20px;">Search for a patient</label>
#Html.EditorFor(model => model.SearchText, new { htmlAttributes = new { #class = "form-control", placeholder = "Search...", autocomplete = "off" } })
<div class="checkbox">
<div class="checkbox" style="padding-left:20px; padding-right:20px;">
<label>#Html.EditorFor(model => model.ShowOnlyOpenClients) Show only open clients</label>
</div>
</div>
<button type='submit' name='seach' id='search-btn' class="btn btn-primary"><i class="fa fa-search"></i>Search</button>
}
Suggestion: As you have used the #using(Html.BeginForm()) which will any way going to convert to <form> tag so instead of using another <form class="form-inline"> inside it is creating the confusion please you may remove it.
I hope this will solve your problem.

Ajax BeginForm POST using MVC and Razor

I keep getting a 404 and searching all over SO and cannot target the issue here. The form is the result of a render action and appears on the home page (home controller). However, I want it to post a different controller action and it keeps giving me a 404. I have included all the correct script for unobtrusive javascript as well as the necessary web.config settings and I'm unable to come across a similar problem from my research.
This is the partial with the form that is being rendered:
#model AFS.Models.SearchLocationModel
<div class="site-search-module">
<div class="site-search-module-inside">
#using (Ajax.BeginForm("SearchCare", "LevelOfCare", null, new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.Replace, UpdateTargetId = "searchDiv" }, new { #class = "search-form", enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="row">
<div class="col-md-12">
<h5>Select a category</h5>
#Html.DropDownListFor(x => x.Level, Model.LevelSelectList, new { #class = "form-control input-lg selectpicker" })
</div>
<div class="col-md-12">
<h5>Enter location</h5>
<input type="text" id="Location" name="Location" class="form-control input-lg selectpicker" placeholder="City, State OR Zip Code" required />
</div>
<div class="col-md-12"> <button type="submit" class="btn btn-primary btn-block btn-lg search"><i class="fa fa-search"></i> Search</button> </div>
</div>
}
</div>
The controller action is:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SearchCare(SearchLocationModel model)
{
if (ModelState.IsValid)
{
SearchLocationModel geocodeModel = Geocode(new SearchLocationModel() { Level = model.Level, Location = model.Location });
if (geocodeModel.Status == "OK")
{
Session["level"] = model.Level;
return RedirectToRoute("LevelCity", new { level = model.Level, state = geocodeModel.State, city = geocodeModel.City, latitude = geocodeModel.Latitude, longitude = geocodeModel.Longitude });
}
else
{
ModelState.AddModelError(string.Empty, "Please enter City, State OR Zip Code.");
return RedirectToAction("SearchWidget", "Home");
}
}
else
{
return RedirectToAction("SearchError");
}
}

Upload file along with text in Create view

My first .Net/MVC project, I generated a view that allows me to list, edit, and create items in a database, and I would like to add a file upload control to the Create page, to just upload one file.
I understand that within [HttpPost] I need "public ActionResult Index(HttpPostedFileBase file)" but my current [HttpPost] is like this: "public ActionResult Create(lm_pics lm_pics)".
Why do you have 2 file inputs? Why do you have 2 forms? Isn't the first form sufficient (assuming of course you add the enctype="multipart/form-data" attribute to it as you cannot upload files without it)?:
#model PictureUploader_MVC.Models.lm_pics
#{
ViewBag.Title = "Create";
}
<h2>Upload Picture</h2>
#using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>lmit_pics</legend>
<div class="editor-label">
#Html.LabelFor(model => model.brand)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.brand)
#Html.ValidationMessageFor(model => model.brand)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.enabled)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.enabled)
#Html.ValidationMessageFor(model => model.enabled)
</div>
<div>
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
</div>
</fieldset>
<button type="submit">Create</button>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
and your controller action that will process the form submission:
[HttpPost]
public ActionResult Create(lm_pics lm_pics, HttpPostedFileBase file)
{
...
}

Resources