问题描述
我将 ASP.NET MVC 5 与实体框架和 Owin/Identity 一起用于用户帐户身份验证。 将各种表单属性与 HttpPostedFileBase 文件组合到数据库时,我的控制器的 Create() 方法似乎按预期工作。但是,每次我尝试在 Edit() 方法中修改同一实体时,HttpPostedFileBase 文件都会返回 null。表单数据的其余部分在编辑中发布并持久保存到数据库中,但我似乎永远无法在编辑方法中将文件发布到控制器。可能与我缺少的某种授权配置有关?
我还可以在 DevTools 中的“请求标题 > 表单数据”下看到正确的文件名和数据至少正在尝试加载到“编辑”帖子中,但它似乎在两者之间的某个地方丢失了。
任何帮助都是超级笨蛋!
(创建.cshtml)
@model GivingTree.Web.Models.FruitTree
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm("Create","FruitTree",null,FormMethod.Post,new { enctype = "multipart/form-data",role="form",@class = ""}))
{
@Html.AntiForgeryToken()
<div>
@Html.ValidationSummary(true,"",new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Name,htmlAttributes: new { @class = "col col-form-label" })
<div class="col">
@Html.EditorFor(model => model.Name,new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name,new { @class = "text-danger" })
</div>
</div>
...
<div class="form-group">
@Html.Label("fileUpload",new {@class = "col col-form-label"})
<div class="col">
<input type="file" name="fileUpload" id="fileUpload" />
</div>
</div>
@Html.Partial("_GoogleMapsBlock")
<div class="form-group">
<div class="col">
<input id="submit" type="submit" name="submit" value="Create" class="btn btn-dark" />
</div>
</div>
</div>
}
(编辑.cshtml)
@model GivingTree.Web.Models.FruitTree
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm("Edit",new { encytype = "multipart/from-data",role = "form",@class = ""}))
{
@Html.AntiForgeryToken()
<div>
@Html.ValidationSummary(true,new { @class = "text-danger" })
@Html.HiddenFor(model => model.Id)
...
<div class="form-group">
@Html.Label("fileUpload",new {@class = "col col-form-label"})
<div class="col">
<input type="file" name="fileUpload" id="fileUpload" />
</div>
</div>
<div class="form-group">
<div class="col">
<input id="submit" type="submit" name="submit" value="Create" class="btn btn-dark" />
</div>
</div>
</div>
(FileUpload.cs)
using System.ComponentModel.DataAnnotations;
namespace GivingTree.Web.Models
{
public class FileUpload
{
public int FileUploadId { get; set; }
[StringLength(255)]
public string FileUploadName { get; set; }
[StringLength(100)]
public string ContentType { get; set; }
public byte[] Content { get; set; }
public FileUploadType FileUploadType { get; set; }
public int FruitTreeId { get; set; }
// using virtual to establish the one-to-many relationship with the FruitTree class
public virtual FruitTree FruitTree { get; set; }
}
}
(FileUploadType.cs)
namespace GivingTree.Web.Models
{
public enum FileUploadType
{
Avatar = 1,Photo
}
}
(FileUploadController.cs)
using System.Web.Mvc;
using GivingTree.Web.DAL;
using GivingTree.Web.Models;
namespace GivingTree.Web.Controllers
{
public class FileUploadController : Controller
{
private GivingTreeDbContext _db = new GivingTreeDbContext();
// This obtains the file based on the id value passed in the query string,then it returns the image to the browser as a FileResult
// GET: /FileUpload/
public ActionResult Index(int? id)
{
FileUpload filetoRetrieve = _db.FileUploads.Find(id);
return File(filetoRetrieve.Content,filetoRetrieve.ContentType);
}
}
}
(果树.cs)
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace GivingTree.Web.Models
{
public class FruitTree
{
public int Id { get; set; }
[required]
[display(Name="Post Title")]
public string Name { get; set; }
[required]
[display(Name="Type of Fruit")]
public FruitType Fruit { get; set; }
[required]
[DataType(DataType.Text)]
[display(Name="Post Description")]
public string Description { get; set; }
[required]
[display(Name="Latitude")]
public double Latitude { get; set; }
[required]
[display(Name="Longitude")]
public double Longitude { get; set; }
// completes the association of the one-to-many relationship with the FileUpload entity
[displayFormat(ConvertEmptyStringToNull=false)]
[display(Name="Upload a Photo")]
public virtual ICollection<FileUpload> FileUploads { get; set; }
}
}
(FruitTreeController.cs)
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Name,Fruit,Description,Latitude,Longitude")]FruitTree tree,HttpPostedFileBase fileUpload)
{
try
{
if (ModelState.IsValid)
{
// Extracts the binary data from the request and populates a new File entity instance which is ready to be added to the FruitTree's File collection.
if (fileUpload?.ContentLength > 0)
{
// create the new File object and assign the properties given by the upload parameter
FileUpload photo = new()
{
FileUploadName = Path.GetFileName(fileUpload.FileName),FileUploadType = FileUploadType.Photo,ContentType = fileUpload.ContentType
};
// the binary data is obtained from the InputStream prop,and a BinaryReader object is used to read that data into the Content property of the File object.
using (var reader = new BinaryReader(fileUpload.InputStream))
{
photo.Content = reader.ReadBytes(fileUpload.ContentLength);
}
// add the new file object to the tree object
tree.FileUploads = new List<FileUpload> { photo };
}
// save to database
_db.FruitTrees.Add(tree);
_db.SaveChanges();
return RedirectToAction("Index");
}
}
catch (RetryLimitExceededException dex )
{
ModelState.AddModelError("Unable to save changes",dex);
}
return View(tree);
}
// GET: FruitTrees/Edit/5
[HttpGet]
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
// Returns all of the file types associated with the given id
FruitTree tree = _db.FruitTrees.Include(s => s.FileUploads).SingleOrDefault(s => s.Id == id);
if (tree == null)
{
return HttpNotFound();
}
return View(tree);
}
// POST: FruitTrees/Edit/5
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int? id,HttpPostedFileBase fileUpload)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var treetoUpdate = _db.FruitTrees.Find(id);
if (ModelState.IsValid)
{
if (TryUpdateModel(treetoUpdate,new string[] {"Name","Fruit","Description","Latitude","Longitude"}))
{
try
{
if (fileUpload != null && fileUpload.ContentLength > 0)
{
if (treetoUpdate.FileUploads.Any(f => f.FileUploadType == FileUploadType.Photo))
{
_db.FileUploads.Remove(treetoUpdate.FileUploads.First(f =>
f.FileUploadType == FileUploadType.Photo));
}
var photo = new FileUpload
{
FileUploadName = System.IO.Path.GetFileName(fileUpload.FileName),ContentType = fileUpload.ContentType
};
using (var reader = new System.IO.BinaryReader(fileUpload.InputStream))
{
photo.Content = reader.ReadBytes(fileUpload.ContentLength);
}
treetoUpdate.FileUploads = new List<FileUpload> {photo};
}
_db.Entry(treetoUpdate).State = EntityState.Modified;
_db.SaveChanges();
return RedirectToAction("Index");
}
catch (RetryLimitExceededException dex)
{
ModelState.AddModelError(
"Unable to save changes.",dex);
}
}
}
return View(treetoUpdate);
}
(GivingTreeDbContext.cs)
using GivingTree.Web.Models;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
namespace GivingTree.Web.DAL
{
public class GivingTreeDbContext : DbContext
{
public DbSet<FruitTree> FruitTrees { get; set; }
public DbSet<FileUpload> FileUploads { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
}
```
(Startup.Auth.cs)
```
using System;
using System.Configuration;
using GivingTree.Web.Models;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.Google;
using Owin;
namespace GivingTree.Web
{
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context,user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
// Configure the sign in cookie
app.UseCookieAuthentication(new CookieAuthenticationoptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,CookieName = "GivingTreeApplicationCookie",LoginPath = new PathString("/Account/Login"),Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager,ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),regenerateIdentity: (manager,user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie,TimeSpan.FromMinutes(5));
// Enables the application to remember the second login verification factor such as phone or email.
// Once you check this option,your second step of verification during the login process will be remembered on the device where you logged in from.
// This is similar to the RememberMe option when you log in.
app.UseTwoFactorRememberbrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberbrowserCookie);
app.UseFacebookAuthentication(
appId: ConfigurationManager.AppSettings["Authentication:Facebook:AppId"],appSecret: ConfigurationManager.AppSettings["Authentication:Facebook:AppSecret"]);
app.UseGoogleAuthentication(new GoogleOAuth2Authenticationoptions()
{
ClientId = ConfigurationManager.AppSettings["Googleoauth2clientId"],ClientSecret = ConfigurationManager.AppSettings["Googleoauth2clientSecret"]
});
}
}
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)