Making HttpPostedFileBase Required in MVC [duplicate] - asp.net-mvc

I have a couple of files I need to save in addition to some simple scalar data. Is there a way for me to validate that the files have been sent along with the rest of the form data? I'm trying to use the [Required] attribute, but it doesn't seem to be working.

The following worked for me.
Model:
public class MyViewModel
{
[Required]
public HttpPostedFileBase File { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new MyViewModel());
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var fileName = Path.GetFileName(model.File.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data"), fileName);
model.File.SaveAs(path);
return RedirectToAction("Index");
}
}
View:
<% using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" })) { %>
<input type="file" name="file" />
<%= Html.ValidationMessageFor(x => x.File) %>
<input type="submit" value="OK" />
<% } %>

Related

Pass id from view to controller

Actually I'm the beginner in the MVC. And simple question:
For example I have ViewModel for the page of Category:
public class CategoryViewModel
{
public int ProductId {get;set;}
public int CategoryId {get;set;}
public string ProductName {get;set;}
public string CategoryName {get;set;}
}
In the controller I just pass CategoryId and CategoryName to the view:
public ActionResult Index()
{
CategoryViewModel categoryViewModel = new CategoryViewModel();
categoryViewModel.CategoryId = catId; \\Get from DB
categoryViewModel.CategoryName = catName; \\Get from DB
return View("Category", categoryViewModel);
}
Then on the View I need to add Product to this Category:
<form action=#Url.Action("AddProduct", "Category") method="POST" enctype = "multipart/form-data">
<textarea name ="ProductName"></textarea>
<input type="submit" value="Add"/>
</form>
And in the controller for AddProduct:
[HttPost]
public ActionResult AddPost(CategoryViewModel categoryViewModel)
{
var productName = categoryViewModel.ProductName;
var categoryId = ?
ProductRepository.AddProductToCategory(productName, categoryId);
return new EmptyResult();
}
Question: How to get the CategoryId? Or maybe there is another approach?
Change your view to include a control for the CategoryId property
#model CategoryViewModel
#using(Html.BeginForm("AddProduct", "Category"))
{
#Html.HiddenFor(m => m.CategoryId)
#Html.TextAreaFor(m => m.ProductName)
<input type="submit" value="Add" />
}
Note, always use strongly types html helpers to generate your html.
Thx for Stephen Muecke
Also you can pass id from (form self) and another properties you want, but you must definition in input action method.
#model CategoryViewModel
#using (Html.BeginForm("AddProduct", "Category", new { id = Model.CategoryId }, FormMethod.Post, new { }))
{
#Html.TextAreaFor(m => m.ProductName)
<input type="submit" value="Add" />
}
Action method :
[HttPost]
public ActionResult AddPost(CategoryViewModel categoryViewModel,int id)
{
var productName = categoryViewModel.ProductName;
var categoryId = id
ProductRepository.AddProductToCategory(productName, categoryId);
return new EmptyResult();
}
i hope this help you.

Uploading Files into Database with ASP.NET MVC

I want to give a facility on my form for user to upload files and save in Database.
How is this done in ASP.NET MVC.
What DataType to write in my Model Class. I tried with Byte[], but during the scaffolding the solution could not generate the appropriate HTML for it in the corresponding View.
How are these cases handled?
You could use a byte[] on your model and a HttpPostedFileBase on your view model. For example:
public class MyViewModel
{
[Required]
public HttpPostedFileBase File { get; set; }
}
and then:
public class HomeController: Controller
{
public ActionResult Index()
{
var model = new MyViewModel();
return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
byte[] uploadedFile = new byte[model.File.InputStream.Length];
model.File.InputStream.Read(uploadedFile, 0, uploadedFile.Length);
// now you could pass the byte array to your model and store wherever
// you intended to store it
return Content("Thanks for uploading the file");
}
}
and finally in your view:
#model MyViewModel
#using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
#Html.LabelFor(x => x.File)
#Html.TextBoxFor(x => x.File, new { type = "file" })
#Html.ValidationMessageFor(x => x.File)
</div>
<button type="submit">Upload</button>
}

Model is null when form submitted

When I hit submit, the file parameter is null.
public ActionResult Create()
{
return View(new FileViewModel());
}
[HttpPost]
[InitializeBlobHelper]
public ActionResult Create(FileViewModel file)
{
if (ModelState.IsValid)
{
//upload file
}
else
return View(file);
}
public class FileViewModel
{
internal const string UploadingUserNameKey = "UserName";
internal const string FileNameKey = "FileName";
internal const string Folder = "files";
private readonly Guid guid = Guid.NewGuid();
public string FileName
{
get
{
if (File == null)
return null;
var folder = Folder;
return string.Format("{0}/{1}{2}", folder, guid, Path.GetExtension(File.FileName)).ToLowerInvariant();
}
}
[RequiredValue]
public HttpPostedFileBase File { get; set; }
}
Here is the cshtml:
#model MyProject.Controllers.Admin.FileViewModel
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_BackOfficeLayout.cshtml";
}
#using (Html.BeginForm("Create", "Files", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<fieldset>
<legend>Create</legend>
<div class="editor-label">
#Html.LabelFor(model => model.File)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.File, new { type = "file" })
#Html.ValidationMessageFor(model => model.File)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
It's naming conflict and binder trying to bind your File property to FileViewModel object with file name, that's why you get null. POST names are case-insensitive.
Change:
public ActionResult Create(FileViewModel file)
To:
public ActionResult Create(FileViewModel model)
or to any other name
This solved my issue as well. It was a name that I was using that was similar to the model, which was similar to the variable I assigned the posted model too. once I sorted out the field name all worked as expected.
Of course the error was not helpful in pointing this out.

Forms collection does not contain input file (ASP.Net MVC 3)

#using (Html.BeginForm("Edit", "MyController", FormMethod.Post, new { enctype="multipart/form-data"}))
{
#Html.EditorFor(model => model.Name)
<input type="file" name="fileUpload" id="fileUpload" />
<input type="image" name="imb_save" src="/button_save.gif" alt="" value="Save" />
}
Submitted form and model are passed in this action:
[HttpPost]
public ActionResult Edit(MyModel mymodel, FormCollection forms)
{
if (string.IsNullOrEmpty(forms["fileUpload"]))
{
//forms["fileUpload"] does not exist
}
//TODO: something...
}
Why does not forms contain fileUpload? But it contains other inputs. How can I get content of my uploader?
Thanks.
Take a look at the following blog post for handling file uploads in ASP.NET MVC. You could use HttpPostedFileBase in your controller instead of FormCollection:
[HttpPost]
public ActionResult Edit(MyModel mymodel, HttpPostedFileBase fileUpload)
{
if (fileUpload != null && fileUpload.ContentLength > 0)
{
// The user uploaded a file => process it here
}
//TODO: something...
}
You could also make this fileUpload part of your view model:
public class MyModel
{
public HttpPostedFileBase FileUpload { get; set; }
...
}
and then:
[HttpPost]
public ActionResult Edit(MyModel mymodel)
{
if (mymodel.FileUpload != null && mymodel.FileUpload.ContentLength > 0)
{
// The user uploaded a file => process it here
}
//TODO: something...
}

ASP.NET MVC File Uploading

HI there,
My model (partial)
public class Document : HttpPostedFileBase
{
public string DocumentTitle { get; set; }
public string DocumentType { get; set; }
My action
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AddDocumentToVault(Document model)
{
foreach (string upload in Request.Files)
{
if (!Request.Files[upload].HasFile()) continue;
_documentAggregator.Add(model);
_documentAggregator.Commit();
}
return PSDocumentVaultPartial();
}
File uploader
<% using (Html.BeginForm("AddDocumentToVault", "PersonalSpace", FormMethod.Post, new { enctype = "multipart/form-data" }))
{%>
<input type="file" id="Document" runat="server" name="Document"/>
<input id="AddDocument" type="submit" value="Upload" style="display:none"/>
<% } %>
The problem I am having is that when the AddDocument button is pressed it's passing an empty model to the action in my controller. And the base properties in HttpPostedFileBase give a System.NotImplementException.
Can anyone tell me what I need to do to correctly pass my model to my action?
It's an issue with HttpPostedFileBase and model binding. See ASP.NET MVC posted file model binding when parameter is Model

Resources