Reputation: 561
I have a file field which is to be used to upload images and at the same time save the file path in the database. I followed this sample tutorial and adapted my code. Below is my model
using System;
using System.Web;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BOL
{
public class TeamValidation
{
[Key]
public int teamID { get; set; }
[Required(ErrorMessage = "Please Enter Your Team Name")]
[Display(Name = "Team Name")]
public string teamName { get; set; }
[DisplayName("Team Picture")]
[Required(ErrorMessage = "Please Upload Team Picture")]
[ValidateFile]
public HttpPostedFileBase teamPicture { get; set; }
//public string teamPicture { get; set; }
[Required]
[Display(Name = "Description")]
public string description { get; set; }
//[AllowHtml]
[Required(ErrorMessage = "Please Enter Team Content")]
[Display(Name = "Content")]
[MaxLength(200)]
public string content { get; set; }
}
//Customized data annotation validator for uploading file
public class ValidateFileAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
int MaxContentLength = 1024 * 1024 * 3; //3 MB
string[] AllowedFileExtensions = new string[] { ".jpg", ".gif", ".png" };
var file = value as HttpPostedFileBase;
if (file == null)
return false;
else if (!AllowedFileExtensions.Contains(file.FileName.Substring(file.FileName.LastIndexOf('.'))))
{
ErrorMessage = "Please upload Your Photo of type: " + string.Join(", ", AllowedFileExtensions);
return false;
}
else if (file.ContentLength > MaxContentLength)
{
ErrorMessage = "Your Photo is too large, maximum allowed size is : " + (MaxContentLength / 1024).ToString() + "MB";
return false;
}
else
return true;
}
}
[MetadataType(typeof(TeamValidation))]
public partial class team
{
[Key]
public int teamID { get; set; }
public string teamName { get; set; }
public string teamPicture { get; set; }
public string description { get; set; }
public string content { get; set; }
}
}
and here is the controller
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using BOL;
namespace TeamBuildingCompetition.Areas.Admin.Controllers
{
public class TeamController : BaseAdminController
{
// GET: Admin/Team
public ActionResult Index()
{
return View();
}
public ActionResult teamView()
{
var teamList = objBs.teamBs.GetALL();
return View(teamList);
}
[HttpPost]
public ActionResult Create(team objTeam)
{
try
{
if (ModelState.IsValid)
{
var fileName = Path.GetFileName(objTeam.teamPicture.FileName);
var path = Path.Combine(Server.MapPath("~/Content/Upload"), fileName);
objTeam.teamPicture.SaveAs(path);
TempData["Msg"] = "Created Successfully!";
objBs.teamBs.Insert(objTeam);
return RedirectToAction("Index");
}
else
{
return View("Index");
}
}
catch (Exception e1)
{
TempData["Msg"] = "Create Failed! :" + e1.Message;
return RedirectToAction("Index");
}
}
}
}
I have the errors in the snip below so I'm not able to run the file. Below is the squiggly line of error from the controller:
and also squiggly line in the model as shown below:
On hovering over the Squiggly lines, I had this error
For the TeamValidation.cs The Error is Generate Class for HttpPostedFileBase
While the error on the TeamController for the squiggly line .FileName is 'string' does not contain a defination for 'FileName' and no extension method 'FileName' accepting a first arguement of type 'string'
Upvotes: 0
Views: 1049
Reputation:
Your problem is the use a partial classes and the [MetadataType]
attribute on class team
. Your data model has property string teamPicture
and your metadata class has a conflicting property HttpPostedFileBase teamPicture
. Your controller method has parameter team objTeam
so objTeam.teamPicture.FileName
throws an error because teamPicture
is typeof string
. To solve this, remove the [MetadataType]
attribute from your data model, and use a view model to represent what you want to edit in the view
Data model (in namespace BOL)
public class team
{
[Key]
public int teamID { get; set; }
public string teamName { get; set; }
public string teamPicture { get; set; }
public string description { get; set; }
public string content { get; set; }
}
Then create a new folder in your project for the view model (say ViewModels
). Note the teamID
should not be required since the view is for creating a new team
public class TeamVM
{
[Required(ErrorMessage = "Please Enter Your Team Name")]
[Display(Name = "Team Name")]
public string TeamName { get; set; }
[DisplayName("Team Picture")]
[Required(ErrorMessage = "Please Upload Team Picture")]
[ValidateFile]
public HttpPostedFileBase TeamPicture { get; set; }
[Required]
[Display(Name = "Description")]
public string Description { get; set; }
[Required(ErrorMessage = "Please Enter Team Content")]
[Display(Name = "Content")]
[MaxLength(200)]
public string Content { get; set; }
}
Your GET method should initialize and return an instance of TeamVM
[HttpGet]
public ActionResult Create()
{
TeamVM model = new TeamVM();
return View(model);
}
and the view will be @model yourAssembly.TeamVM
Then the POST method will be
[HttpPost]
public ActionResult Create(TeamVM model)
{
....
var fileName = Path.GetFileName(model.TeamPicture.FileName);
var path = Path.Combine(Server.MapPath("~/Content/Upload"), fileName);
model.TeamPicture.SaveAs(path);
// map the view model to a new instance of the data model
team objTeam = new team
{
teamName = model.TeamName,
teamPicture = path,
description = model.Description,
content = model.Content
};
// save and redirect
objBs.teamBs.Insert(objTeam);
....
}
Upvotes: 2
Reputation: 1651
You use MetadataTypeAttribute and in documentation is:
You then define the metadata type as a normal class, except that you declare simple properties for each of the members to which you want to apply validation attributes.
Example from documentation:
[MetadataType(typeof(ProductMetadata))]
public partial class Product
{
... Existing members defined here, but without attributes or annotations ...
}
Then your class team should be like this:
[MetadataType(typeof(TeamValidation))]
public partial class team
{
[Key]
public int teamID { get; set; }
public string teamName { get; set; }
public HttpPostedFileBase teamPicture { get; set; }
public string description { get; set; }
public string content { get; set; }
}
Upvotes: 1