File Upload in ASP.NET MVC 5 - asp.net

I am unable to upload file in folder. I am not able to find the mistake. The UploadFile View returns on same view after uploading file.
Model Class:
public class Upload
{
public int UploadId { get; set; }
public string UploadTitle { get; set; }
public string UploadURL { get; set; }
}
Here is the Controller(FileUpload) Action:
public ActionResult UploadFile(HttpPostedFileBase file, Upload upload)
{
if (ModelState.IsValid)
{
if (file != null)
{
string fil = System.IO.Path.GetFileName(file.FileName);
string path = System.IO.Path.Combine(Server.MapPath("/Content/Uploads/Files"), fil);
file.SaveAs(path);
upload.UploadURL = "/Content/Uploads/Files/" + file.FileName;
}
db.Uploads.Add(upload);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(upload);
}
In my View:
#using (Html.BeginForm("UploadFile, "FileUpload", FormMethod.Post, new { enctype = "multipart/Form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<div class="control-label col-md-2">
<label for="file">Upload Image for Slide:</label>
</div>
<div class="col-md-10">
<input type="file" name="file" id="file" style="width:50%" />
</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>
}

Hi I have tried your same code its works for me.
Controller
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
if (file != null)
{
string fil = System.IO.Path.GetFileName(file.FileName);
string path = System.IO.Path.Combine(Server.MapPath("/Content/Uploads/Files"), fil);
file.SaveAs(path);
}
return RedirectToAction("Index");
}
return View("UploadFile");
}
View
#using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new { enctype = "multipart/Form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<div class="control-label col-md-2">
<label for="file">Upload Image for Slide:</label>
</div>
<div class="col-md-10">
<input type="file" name="file" id="file" style="width:50%" />
</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>
}
I have found small mistake in you code in Html.BeginForm in action name " (double quotes is missing)

I forgot to mention the required field on UploadURL in above model class:
public class Upload
{
public int UploadId { get; set; }
public string UploadTitle { get; set; }
[Required]
public string UploadURL { get; set; }
}
Required Field validation on UploadURL field restricted the file upload here. I removed the Required field validation from the field.

Related

How to make selection (choose one of the two strings with select input in html) with Entity Framework?

I want to make the user only choose between two strings, Internal or Consigned, to be inserted into the InternalConsigned column of a database. How do I do that?
This is my current code:
Equipment.cs model class:
public class Equipment
{
[Key]
public int Id { get; set; }
[Required]
[DisplayName("Equipment Name")]
public string Name { get; set; }
[Required]
public int Amount { get; set; }
[Required]
public string Status { get; set; }
[ForeignKey("DepartmentId")]
public int DepartmentId { get; set; }
public Department? Department { get; set; }
[Required]
public string InternalConsigned { get; set; }
public DateTime EOLDate { get; set; }
}
Create action method:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Id,Name,Amount,Status,DepartmentId,InternalConsigned,EOLDate")] Equipment equipment)
{
if (ModelState.IsValid)
{
_context.Add(equipment);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
ViewData["DepartmentId"] = new SelectList(_context.Departments, "Id", "Name", equipment.DepartmentId);
return View(equipment);
}
Create.cshtml:
#model Equipment
#{
ViewData["Title"] = "Create";
}
<h4>Equipment</h4>
<hr />
<div class="row">
<div class="col-md-4">
<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">
<label asp-for="Amount" class="control-label"></label>
<input asp-for="Amount" class="form-control" />
<span asp-validation-for="Amount" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Status" class="control-label"></label>
<input asp-for="Status" class="form-control" />
<span asp-validation-for="Status" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="DepartmentId" class="control-label"></label>
<select asp-for="DepartmentId" class ="form-control" asp-items="ViewBag.DepartmentId"></select>
</div>
<div class="form-group">
<label asp-for="InternalConsigned" class="control-label"></label>
<input asp-for="InternalConsigned" class="form-control" />
<span asp-validation-for="InternalConsigned" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="EOLDate" class="control-label"></label>
<input asp-for="EOLDate" class="form-control" />
<span asp-validation-for="EOLDate" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
I know I have to use the select tag in the View, but I'm not sure what to write in the Controller.
If I don't misunderstand your question, You want to write a dropdown list with two options Internal or Consigned, So you can refer to this simple demo, Hope it can help you.
List<SelectListItem> test = new List<SelectListItem>();
test.Add(new SelectListItem { Text = "Internal ", Value = "Internal " });
test.Add(new SelectListItem { Text = "Consigned", Value = "Consigned" });
ViewData["demo"] = test;
Then in the view:
<select asp-for="InternalConsigned" asp-items="#ViewBag.demo"></select>
Demo:

Some model properties always null on post, modelbinding issue

I am making a part of a website where you can update your profile. The profile is tied to the user which is an extension of Microsofts Identity.
The problem is that LastName and FirstName is always null after making a post request.
I would like to think that if this was a ModelState error I would have caught it through !ModelState.IsValid.
https://i.gyazo.com/eea1e3465427eba5a731947473fca821.mp4
Model
using Microsoft.AspNetCore.Identity;
using System;
namespace Certificate_Wiki.Models {
public class CertificateUser : IdentityUser {
public string FirstName { get; set; }
public string LastName { get; set; }
public string Website { get; set; }
public string Occupation { get; set; }
public string Country { get; set; }
public string Description { get; set; }
public String ProfilePictureUrl { get; set; }
public Byte[] ProfilePicture { get; set; }
public bool isPrivate { get; set; }
}
}
cshtml
#{
ViewData["Title"] = "Edit Profile";
}
#model Certificate_Wiki.Models.CertificateUser
<link rel="stylesheet" href="~/css/pages/ProfileEdit.css" media="all" />
<div class="background"></div>
<div class="content">
<div class="content-image">
<img src="~/images/profile/Component 1 – 1.png" alt="" />
</div>
<div class="content-profile">
<div class="profile-image">
<img src="https://www.pngitem.com/pimgs/m/78-786293_1240-x-1240-0-avatar-profile-icon-png.png" alt="error loading image" />
</div>
<div class="profile-form">
<h2>#User.Identity.Name</h2>
<div asp-validation-summary="All">
</div>
<form asp-action="Edit" method="post">
<div class="form-row">
<label>First Name</label>
<input asp-for="FirstName" type="text" name="name" />
</div>
<div class="form-row">
<label>Last Name</label>
<input asp-for="LastName" type="text" name="name" />
</div>
<div class="form-row">
<label>Occupation</label>
<input asp-for="Occupation" type="text" name="occupation" />
</div>
<div class="form-row">
<label>Website</label>
<input asp-for="Website" type="url" name="website" />
</div>
<div class="form-row">
<label>Country</label>
<input asp-for="Country" type="text" name="Country" />
</div>
<div class="form-row">
<label>Profile Description</label>
<textarea asp-for="Description" type="text" name="description"></textarea>
</div>
<div class="form-row">
<label>Private Profile</label>
<input asp-for="isPrivate" type="checkbox" name="Private" />
</div>
<div class="form-row">
<button type="submit">Save</button>
</div>
</form>
</div>
</div>
</div>
Controller
[HttpGet]
[Authorize]
[Route("Profile/edit")]
public async Task<IActionResult> EditAsync()
{
var Profile = await userManager.FindByEmailAsync(User.Identity.Name);
if (Profile == null) { return View(); }
return View(Profile);
}
[ValidateAntiForgeryToken]
[HttpPost]
[Authorize]
[Route("Profile/edit")]
public async Task<IActionResult> EditAsync([FromForm]CertificateUser model)
{
//TODO
//Remove CW from single-line if
if (!ModelState.IsValid) { Console.WriteLine("Modelstate invalid"); return View(model); }
var Profile = await userManager.FindByEmailAsync(User.Identity.Name);
if (Profile == null) { return View(); }
//Update database
Profile.FirstName = model.FirstName;
Profile.LastName = model.LastName;
Profile.Description = model.Description;
Profile.Country = model.Country;
Profile.Occupation = model.Occupation;
Profile.Website = model.Website;
await userManager.UpdateAsync(Profile);
Console.WriteLine("Update success");
return RedirectToAction("Index");
}
Note, While I am at it I would also like to ask if there is a "better" or a rather clean way to update the user without profile... = model... for every property to be updated.
If you use the asp-for attribute for input box, then you shouldn't use the name attribute in the same time (or at least use the same value for it).
In your example you set FirstName for asp-for and then just name for the name attribute of the input for FirstName.

Asp.net MVC - input type="file" validation error

i create a form that have 2 input text and 1 input file, when i selected the image and click on submit button an error occurs for the input file
i don't have any validation on input file!
this is my view code:
#model Test.Models.Domain.tblCategory
#{
Layout = null;
}
#using (Html.BeginForm("AddOrEditeCat", "Admin", FormMethod.Post, new {enctype="multipart/form-data",onsubmit="return SubmitCatForm(this)" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(model => model.id)
#Html.HiddenFor(model => model.Pic)
<div class="form-group">
#Html.Label("Title", new { #class = "control-label" })
#Html.EditorFor(model => model.Title, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Title)
</div>
<div class="form-group">
#Html.Label("Text", new { #class = "control-label" })
#Html.EditorFor(model => model.Text, new { htmlAttributes = new { #class = "form-control" } })
</div>
<div class="form-group">
#Html.LabelFor(model=>model.Pic, new { #class = "control-label" })
<img src="#Url.Content(Model.Pic)" style="margin:10px" height="150" width="150" id="imagePreview" />
<input type="file" id="ImageUpload" name="ImageUpload" accept="image/jpeg,image/png" onchange="ShowImagePreview(this,document.getElementById('imagePreview'))" />
</div>
<div class="form-group">
<input type="submit" value="Submit" class="btn btn-primary" />
<input type="reset" value="Reset" class="btn btn-primary btn-danger" />
</div>
}
and this is my model:
public partial class tblCategory
{
public int id { get; set; }
[Required(ErrorMessage = "*")]
public string Title { get; set; }
public string Text { get; set; }
[DisplayName("Image")]
public string Pic { get; set; }
public HttpPostedFileBase ImageUpload { get; set; }
public tblCategory()
{
Pic = "~/Cntent/upload/img/cat/defalt.png";
}
}

Asp.net Cant Post Value to Controller

I want to post email and password to Another Controller's action (to Create )
But values are not posted. When i look at the User1Controller's its writing values are Null like in the screenshot. Please help I'm stuck with this hours and cant understand
ScreenShot
My User1.cs
public partial class Users1
{
public string userEmail { get; set; }
public string userPassword { get; set; }
}
My User1Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "userEmail,userPassword")] Users1 baska)
{
if (ModelState.IsValid)
{
db.Users1.Add(baska);
db.SaveChanges();
return RedirectToAction("Index","Home");
}
return RedirectToAction("Login", "Home");
}
My Login.cshtml file
#using (Html.BeginForm("Create","Users1",FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="custom-login-panel">
<div class="container">
<div class="row">
<div class="col-md-offset-3 col-md-6">
<img class="profile-img" src="~/images/userlogo.svg"
alt="">
<div class="form-login">
<h4 style="color:white;">Giriş ve Kayıt Ekranı</h4>
<div class="form-group">
#Html.EditorFor(m => m.user1.userEmail, new { htmlAttributes = new { #class = "form-control" ,placeholder="Email" } })
#*#Html.ValidationMessageFor(model => model.user1.userEmail, "", new { #class = "text-danger" })*#
</div>
<div class="form-group">
#Html.EditorFor(m => m.user1.userPassword, new { htmlAttributes = new { #class = "form-control", placeholder = "Passwordd" } })
#*#Html.ValidationMessageFor(model => model.user1.userPassword, "", new { #class = "text-danger" })*#
</div>
<div class="wrapper">
<div class="form-group">
<span class="group-btn">
<input style="width:40%;" type="submit" value="Giriş" class="submit btn btn-primary">
<input style="width:40%;" type="submit" value="Kayıt Ol" class="submit btn btn-primary">
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
}
On your Login.cshtml:
you should declare your model.
On your httpget action:
you should declare a new instance of your Users1 class and pass it like a parameter to your return() method.
On your httppost action:
You should receive the model as parameter.
I guess that with these changes, it would work.

Persist values between multiple Posts

Hello I am not able to retain values on multiple posts and “Post1” action function in my in my controller always has MyViewModelObj.Field2 as null .I expect it to retain the old value in the 2nd post
How to I make the MyViewModel model class object persist the values ?
Mymodels.cs ( Model)
namespace RetainTest.Models
{
public class MyViewModel
{
public string Field1 { get; set; }
public string Field2 { get; set; }
public string Field3 { get; set; }
public string Field4 { get; set; }
}
}
RetainView.cshtml ( View )
#model RetainTest.Models.MyViewModel
#{
ViewBag.Title = "RetainView";
}
<h2>RetainView</h2>
#using (Html.BeginForm("Post1", "Retain", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(model => model.Field1);
#Html.HiddenFor(model => model.Field2);
#Html.HiddenFor(model => model.Field3);
#Html.HiddenFor(model => model.Field4);
<div class="form-horizontal">
<h4>MyViewModel</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Field1, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Field1, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Field1, "", new { #class = "text-danger" })
</div>
</div>
#{
if ( Model.Field2 == "Val2")
{
<div class="form-group">
#Html.LabelFor(model => model.Field2, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Field2, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Field2, "", new { #class = "text-danger" })
</div>
</div>
}
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
RetainController.cs ( Controller )
namespace RetainTest.Models
{
public class RetainController : Controller
{
// GET: Retain
public ActionResult Index()
{
MyViewModel MyViewModelObj = new MyViewModel();
MyViewModelObj.Field1 = "Val1";
return View("RetainView", MyViewModelObj);
}
[HttpPost]
public ActionResult Post1(MyViewModel MyViewModelObj)
{
if (string.IsNullOrEmpty(MyViewModelObj.Field2 ))
{
MyViewModelObj.Field2 = "Val2";
}
return View("RetainView", MyViewModelObj);
}
}
}
Try this:
namespace RetainTest.Models
{
public class MyViewModel
{
[Required(ErrorMessage = "Field1 is required")]
public string Field1 { get; set; }
[Required(ErrorMessage = "Field2 is required")]
public string Field2 { get; set; }
public string Field3 { get; set; }
public string Field4 { get; set; }
}
}
#model RetainTest.Models.MyViewModel
#{
ViewBag.Title = "RetainView";
}
<h2>RetainView</h2>
#using (Html.BeginForm("Post1", "Retain", FormMethod.Post, new { id = "form", enctype = "multipart/form-data"}))
{
#Html.AntiForgeryToken()
#Html.HiddenFor(model => model.Field1);
#Html.HiddenFor(model => model.Field2);
#Html.HiddenFor(model => model.Field3);
#Html.HiddenFor(model => model.Field4);
<div class="form-horizontal">
<h4>MyViewModel</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<Label for="Field1" class="control-label col-md-2">Field1 </label>
<div class="col-md-10">
#if(Model.Field1 == "Val1")
{
<input type="text" name="Field1" id="Field1" class="form-control" value="#Model.Field1">
}
else
{
<input type="text" name="Field1" id="Field1" class="form-control">
}
<span class="field-validation-valid text-danger"
data-valmsg-for="Field1"
data-valmsg-replace="true">
</span>
</div>
</div>
<div class="form-group">
<Label for="Field2" class="control-label col-md-2">Field2 </label>
<div class="col-md-10">
#if(Model.Field2 == "Val2")
{
<input type="text" name="Field2" id="Field2" class="form-control" value="#Model.Field2">
}
else
{
<input type="text" name="Field2" id="Field2" class="form-control">
}
<span class="field-validation-valid text-danger"
data-valmsg-for="Field2"
data-valmsg-replace="true">
</span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
namespace RetainTest.Models
{
public class RetainController : Controller
{
private MyViewModel MyViewModelObj = new MyViewModel();
// GET
public ActionResult Index()
{
if (Session["MyObj"] != null)
MyViewModelObj = (MyViewModel)Session["MyObj"];
else
MyViewModelObj.Field1 = "Val1";
return View("RetainView", this);
}
[AcceptVerbs(HttpVerbs.Post)]
[ValidateInput(false)]
public ActionResult Post1(FormCollection form)
{
MyViewModelObj.Field1 = form.Get("Field1");
MyViewModelObj.Field2 = form.Get("Field2");
if (string.IsNullOrEmpty(MyViewModelObj.Field2))
MyViewModelObj.Field2 = "Val2";
// here you need to store the data somewhere!
// session, database.
// just an example:
Session.Add("MyObj", MyViewModelObj);
return View("RetainView", this);
}
}
}
I used the session to retain the values of the object but there are a few other ways to store the data. The above code will post the user input to the controller and retain he values in the session.
Got answer from Stephen Muecke
"Your view has a hidden input for each property of your model. The DefaultModelBinder reads the first name/value pair for each property in the request and ignores all others. Since the hidden inputs are first, the values of your EditorFor() methods are ignored. You only ever bind the initial vales of your model, not the edited values (making your form rather pointless). Remove the hidden inputs!"

Resources