I am trying to allow a user to upload an image to our website and I'm not quite sure about how to use this. I have tried to use multiple types to define the image, including System.Drawing.Image and HttpPostedFileWrapper but the #Html.EditorFor always (understandably) brings up its attributes as fields to edit.
In my view I did have, instead of #Html.EditorFor I did have <input type="file" name="imageToUpload" /> but it didn't get taken through to my view as part of the Model? I am quite new to MVC so I am hoping it is something trivial.
Here is my View:
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>New Image</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Description)
#Html.ValidationMessageFor(model => model.Description)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Image)
</div>
<div class="editor-field">
<input type="file" name="imageToUpload" />
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
My Controller:
[HttpPost]
public ActionResult CreateImage(string brand, string collection, ImageEditViewModel imageEditViewModel)
{
string fileName = Guid.NewGuid().ToString();
string serverPath = Server.MapPath("~");
string imagesPath = serverPath + String.Format("Content\\{0}\\Images\\", Helper.Helper.ResolveBrand());
string newLocation = Helper.Helper.SaveImage(fileName, imagesPath, imageEditViewModel.Image.InputStream)
Image image = new Image
{
Collection = ds.Single<Collection>(c => c.Season == collection
&& c.Brand.Name == brand),
Description = imageEditViewModel.Description,
Location = "newLocation",
Order = Helper.Helper.GetImageOrder(brand, collection)
};
ds.InsertOnSubmit<Image>(image);
ds.SubmitChanges();
return RedirectToAction("Brand");
}
And finally the ViewModel:
public class ImageEditViewModel
{
public int CollectionId { get; set; }
public string Description { get; set; }
public HttpPostedFileWrapper Image { get; set; }
public int Order { get; set; }
}
Ensure to specify the correct enctype="multipart/form-data" on your form or you won't be able to upload files:
#using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>New Image</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Description)
#Html.ValidationMessageFor(model => model.Description)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ImageToUpload)
</div>
<div class="editor-field">
<input type="file" name="imageToUpload" />
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
And if you wanted to use an EditorFor helper to generate the file input you could use the following:
<div class="editor-label">
#Html.LabelFor(model => model.ImageToUpload)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ImageToUpload)
</div>
and then define a custom editor template for the HttpPostedFileBase type (see below that you need to modify your model to use this type actually). So the editor template in ~/Views/Shared/EditorTemplates/HttpPostedFileBase.cshtml:
#model HttpPostedFileBase
#Html.TextBox("", null, new { type = "file" })
and on your view model use the HttpPostedFileBase type and make sure that the name of the property matches the name of the file input on your form:
public class ImageEditViewModel
{
public int CollectionId { get; set; }
public string Description { get; set; }
public HttpPostedFileBase ImageToUpload { get; set; }
public int Order { get; set; }
}
Also make sure to checkout the following blog post.
Related
I'm going straight to the point here guys,
I have a form. when I save the form... it only gets the firstname, middlename and lastname.. it doesn't get the files... however, if I only get the photo and comment out other inputs... the photo is captured on my model.. I dunno why it behaves like this.. I'm really new to asp.net mvc.. so please bear with me..
#model Impulse.ViewModels.AgentViewModel
#{
ViewBag.Title = "AgentForm";
Layout = "~/Views/Shared/_SiteLayout.cshtml";
}
<div class="custom-container">
<h1 class="title"><strong>Add New Agent</strong></h1>
<hr />
#using (Html.BeginForm("Save", "Agent", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="row">
<div class="col-md-3">
<div id="preview">
<img src="~/Content/Assets/no-image.png" id="profile_image" class="img-thumbnail" />
</div>
<div class="form-group">
<label>Profile Picture</label>
<input type="file" name="photo" id="photo" />
</div>
</div>
<div class="col-md-9">
<div class="row">
<div class="col-md-4">
<div class="form-group">
#Html.LabelFor(m => m.Agent.FirstName)
#Html.TextBoxFor(m => m.Agent.FirstName, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Agent.FirstName)
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="form-group">
#Html.LabelFor(m => m.Agent.MiddleName)
#Html.TextBoxFor(m => m.Agent.MiddleName, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Agent.MiddleName)
</div>
</div>
</div>
<div class="row">
<div class="col-md-4">
<div class="form-group">
#Html.LabelFor(m => m.Agent.LastName)
#Html.TextBoxFor(m => m.Agent.LastName, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Agent.LastName)
</div>
</div>
</div>
</div>
</div>
<input type="submit" class="btn btn-primary" value="Save" />
}
</div>
Controller
[HttpPost]
public ActionResult Save(AgentModel agent)
{
//I debug here to see the data passed by my view
return Content("Sample");
}
Model
public class AgentModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
[FileSize(10240)]
[FileTypes("jpg,jpeg,png")]
public HttpPostedFileBase photo { get; set; }
}
you can try like this
Model
public class UploadFileModel
{
public UploadFileModel()
{
Files = new List<HttpPostedFileBase>();
}
public List<HttpPostedFileBase> Files { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
}
View
#using (Html.BeginForm("UploadData", "Home", FormMethod.Post, new { encType="multipart/form-data" }))
{
#Html.TextBoxFor(m => m.FirstName)
<br /><br />
#Html.TextBoxFor(m => m.Files, new { type = "file", name = "Files" })<br /><br />
<input type="submit" value="submit" name="submit" id="submit" />
}
Controller
public ActionResult UploadData(UploadFileModel model)
{
var file = model.Files[0];
return View(model);
}
you are binding to view to AgentViewModel so you will get AgentViewModel when you post server. so the parameter to action save should be viewmodel. Or Else change view to bind to AgentModel.
The file control that you have used is html input type. try using below code.
#Html.TextBoxFor(m => Model.File, new { type = "file" , accept=".pdf"})
#Html.ValidationMessageFor(m => Model.File)
I am trying to create a form for updating user info. I am using typed view for model class User:
public class User : MembershipUser, IEntity
{
public virtual int Id { get; set; }
public virtual string Username { get; set; }
public virtual string Password { get; set; }
public virtual string Name { get; set; }
public virtual string Surname { get; set; }
public virtual Role Role { get; set; }
public virtual string ProfileImage { get; set; }
public virtual string About { get; set; }
}
The view looks like this:
using (Html.BeginForm("SaveUser", "BlogUser", FormMethod.Post, new { #class = "form-horizontal", enctype = "multipart/form-data" }))
{
<div class="form-group">
#Html.HiddenFor(x => x.Id)
#Html.HiddenFor(x => x.ProfileImage)
#Html.HiddenFor(x => x.UserName)
#Html.HiddenFor(x => x.Password)
#Html.HiddenFor(x => x.Role)
<div class="col-sm-10">
<label>Jméno</label>
</div>
<div class="col-sm-10">
#Html.TextBoxFor(x => x.Name, new { #class = "form-control" })
#Html.ValidationMessageFor(x => x.Name)
</div>
</div>
<div class="form-group">
<div class="col-sm-10">
<label>Příjmení</label>
</div>
<div class="col-sm-10">
#Html.TextBoxFor(x => x.Surname, new { #class = "form-control" })
#Html.ValidationMessageFor(x => x.Surname)
</div>
</div>
<div class="form-group">
<div class="col-sm-10">
<label>Profilový obrázek</label>
</div>
<div class="col-sm-10">
<input type="file" name="picture" />
#if (!String.IsNullOrEmpty(Model.ProfileImage))
{
<img src="#Url.Content("~/Upload/UserImages/" + Model.ProfileImage)" />
}
</div>
</div>
<div class="form-group">
<div class="col-sm-10">
<label>Něco o mně</label>
</div>
<div class="col-sm-10">
#Html.TextAreaFor(x => x.About, new { #class = "form-control formatedText", #rows = 20 })
#Html.ValidationMessageFor(x => x.About)
</div>
</div>
<div class="form-group">
<div class="col-sm-10">
<button type="submit" class="btn btn-primary btn-lg btn-block">Uložit</button>
</div>
</div>
}
I am getting right user, i have prefilled columns with right details, but after submit it throws exception [Argument Exception “Item with Same Key has already been added”]. I wont even trigger the SaveUser() controller method, so I could atleast debug it. I cant figure out where the problem is. Can you help me?
You could try the following solution: An item with the same key has already been added
It seems like it is the model contains a same property twice, you may want to take out the virtual keyword from properties if it is not necessary.
See also: https://msdn.microsoft.com/en-us/library/9fkccyh4.aspx
I figured it out. I had property called username in parental class MembershipUser.
I am new to ASP.NET MVC and I am having trouble updating the model data and then displaying it my view.
I currently have a MortgageCalculator class that I am using as a model.
public double loan_amount { get; set; }
public double interest { get; set; }
public int loan_duration { get; set; }
public int payments_year { get; set; }
Code for the controller is:
[httpGet]
public ActionResult M_Calculator()
{
var mortgageCalculator = new MortgageCalculator();
return View(mortgageCalculator);
}
[HttpPost]
public ActionResult M_Calculator(MortgageCalculator mortgageCalculator)
{
UpdateModel(mortgageCalculator);
return RedirectToAction("Results");
}
public ActionResult Results (MortgageCalculator mortgageCalculator)
{
return View(mortgageCalculator);
}
Code for my view is:
#using (Html.BeginForm())
{
<fieldset>
<legend>Mortgage Calculator</legend>
<div class="editor-label">
#Html.LabelFor(model => model.loan_amount)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.loan_amount)
</div>
<br />
<div class="editor-label">
#Html.LabelFor(model => model.interest)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.interest)
</div>
<br />
<div class="editor-label">
#Html.LabelFor(model => model.loan_duration)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.loan_duration)
</div>
<br />
<div class="editor-label">
#Html.LabelFor(model => model.payments_year)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.payments_year)
</div>
<br />
<input type="submit" value="Calculate" />
</fieldset>
}
I want to make some calculations on the data that I receive from the user and then show the results in my Results view. I don't have any database. I just want to perform simple calculations on data and show the results. The solution seems to be pretty straight forward but I am stuck. I would appreciate any help.
Instead of redirect user to another action you should return your model with the result populated, like this:
[HttpPost]
public ActionResult M_Calculator(MortgageCalculator mortgageCalculator)
{
UpdateModel(mortgageCalculator);
return View("Results", mortgageCalculator);
}
If you don't want to create another view only to show the results, just remove the first parameter that indicates which view ASP.NET MVC should use, so, it will use the default view.
I have a form and using Grid.MVC to display in same page. When I try run my program, it show error : 'Model' conflicts with the declaration 'System.Web.Mvc.WebViewPage.Model'..
Here the sample of my code
This is my model
public class Course
{
[DisplayName("Customer Name")]
public string customer { get; set; }
[DisplayName("Contact")]
public string contact { get; set; }
[UIHint("DropDownList")]
[Required(ErrorMessage = "Please select the package")]
public int CoursePackageID { get; set; }
[Required]
public int CustomerID { get; set; }
[Required(ErrorMessage = "The date is required")]
[DisplayName("Date Of Register")]
public DateTime dtRegister { get; set; }
[DisplayName("Payment")]
public string payment { get; set; }
public List<CourseObject> lCourse { get; set; }
public class CourseObject
{
public int courseId { get; set; }
[DisplayName("Package")]
public string package { get; set; }
[DisplayName("Date Of Register")]
public DateTime date_register { get; set; }
[DisplayName("Payment")]
public string payment { get; set; }
}
}
And this is my CSHTML (Razor)
#model BangiProject.Models.Course
#using GridMvc.Html
#{
ViewBag.Title = "Register";
}
<h2>
Register</h2>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Course</legend>
<div class="control-label">
#Html.LabelFor(model => model.customer)
</div>
<div class="form-control-static">
#Html.DisplayFor(model => model.customer)
</div>
<div class="control-label">
#Html.LabelFor(model => model.contact)
</div>
<div class="form-control-static">
#Html.DisplayFor(model => model.contact)
</div>
<div class="editor-label">
Category :
</div>
<div class="editor-field">
#Html.DropDownListFor(Model => Model.CoursePackageID, new SelectList(ViewBag.CoursePackage as System.Collections.IEnumerable, "id", "course_name", new { #style = "drop-down" }),
"-Choose Package-", new { id = "cat" })
</div>
<div class="editor-label">
#Html.LabelFor(model => model.dtRegister)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.dtRegister)
#Html.ValidationMessageFor(model => model.dtRegister)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.payment)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.payment)
#Html.ValidationMessageFor(model => model.payment)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div class="row">
#Html.Grid(Model.lCourse).Columns(columns =>
{
columns.Add(c => c.courseId).Titled("ID")
.Sanitized(false)
.Encoded(false)
.RenderValueAs(o => Html.ActionLink("Edit", "Edit", "Merchant", new { id = o.courseId }, null).ToHtmlString());
columns.Add(c => c.package).Titled("Package").Filterable(true);
columns.Add(c => c.date_register).Titled("Date Of Register").Filterable(true);
}).WithPaging(25).Sortable(true)
</div>
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
The error show on this line
#Html.Grid(Model.lCourse).Columns
Please advice...
Usually this means that you're using the reserved "Model" keyword erroneously somewhere. In your case:
#Html.DropDownListFor(Model => Model.CoursePackageID...
Change this to:
#Html.DropDownListFor(model => model.CoursePackageID...
Try changing the line in question as below(lowercase 'm')...
#Html.Grid(model.lCourse).Columns
I have the following view, which fails to validate on Title, and NewsContent. Title validation works but not NewsContent. How can i fix it.
#model Foo.NewsViewModel
#{
ViewBag.Title = "Create";
}
#using (Html.BeginForm("Create", "News", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
<fieldset>
<legend>Category Information</legend>
<div class="editor-label">
#Html.LabelFor(m => m.News.Title)
</div>
<div class="editor-field">
#Html.TextBoxFor(m => m.News.Title)
#Html.ValidationMessageFor(m => m.News.Title)
</div>
<div class="editor-label">
#Html.LabelFor(m => m.News.NewsContent)
</div>
<div class="editor-field" id="container">
#Html.TextAreaFor(m => m.News.NewsContent)
#Html.ValidationMessageFor(m => m.News.NewsContent)
</div>
<div class="editor-label">
#Html.LabelFor(m => m.News.Thumbnail)
</div>
<div class="editor-field">
<input type="file" name="files" id="thumbnail" />
</div>
<div class="editor-label">
#Html.LabelFor(m => m.News.Image)
</div>
<div class="editor-field">
<input type="file" name="files" id="original" />
</div>
<div class="editor-label">
#Html.Label("SelectedCategoryId")
</div>
<div class="editor-field">
#Html.DropDownListFor(m => m.SelectedCategoryId, Model.Categories)
</div>
<div class="editor-label">
Publish
</div>
<div class="editor-field">
#Html.CheckBoxFor(m => m.News.Published, new { #checked = "checked" })
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
</div>
}
and here is the model|:
public class News : IStorable
{
[Required]
[Display(Name = "Title")]
public virtual string Title { get; set; }
[Required]
[Display(Name = "Content")]
public virtual string NewsContent { set; get; }
......
Issue: Title validation works but not NewsContent.
Validations is not work, because of using Html.TextAreaFor() helper to render the "NewsContent" property,
Here is the code to make it work:
Change your model as:
Decorate the 'NewsContent' property with [DataType] attribute and set the data type as 'MultilineText'. This will indicates that the editor for this property should be a multi-line text input.
public class News : IStorable
{
[Required]
[Display(Name = "Title")]
public virtual string Title { get; set; }
[Required()]
[Display(Name = "Content")]
[DataType(DataType.MultilineText)]
public virtual string NewsContent { set; get; }
//....
}
In the view use Html.EditorFor() helper instead of Html.TextAreaFor() for the 'News.NewsContent' property.
//....
<div class="editor-label">
#Html.LabelFor(m => m.News.NewsContent)
</div>
<div class="editor-field" id="container">
#*#Html.TextAreaFor(m => m.News.NewsContent)*#
#Html.EditorFor(m => m.News.NewsContent)
#Html.ValidationMessageFor(m => m.News.NewsContent)
</div>
//....