Try this:
public ActionResult Create(Lugar lugar, HttpPostedFileBase fotosLugar)
{
if (fotosLugar != null && fotosLugar.ContentLength > 0)
{
var contentLength = fotosLugar.ContentLength;
var content = new byte[contentLength];
fotosLugar.InputStream.Read(content, 0, contentLength);
var foto = new Foto { Binary = content };
lugar.FotosLugar = foto;
}
//... eventually return an ActionResult
}
Files are a bit trickier to deal with than normal data because the bytes are contained in a Stream
object. The code above reads the bytes out of the stream so that they can be stored in your EF entity class.
A couple of other notes: It might not be a bad idea to also store the ContentLength
, ContentType
, and possibly FileName
on your Foto
entity. You might also want to consider splitting this entity into 2, so that you can query out the file name, content type, and content length separately from the raw binary file data. We had an issue in our site where we needed to just get the file names, but that query was slow because, since we stored our byte[]
column on the same table as the file name, SQL was returning all of the binary data when all we needed was the string file name. Eventually solved with a model similar to the following:
public class Foto
{
public int Id { get; set; }
public int ContentLength { get; set; }
public string FileName { get; set; }
public string ContentType { get; set; }
public virtual FotoBinary Content { get; set; }
}
public class FotoBinary
{
public int Id { get; set; }
public virtual Foto Owner { get; set; }
public byte[] Value { get; set; }
}
This way, you can query just the string
& int
data separately, and eager load or lazy load the binary data separately when needed. Here is the fluent mapping for the relationship between these 2 entities:
// Foto entity
HasRequired(principal => principal.Content)
.WithRequiredPrincipal(dependent => dependent.Owner)
.WillCascadeOnDelete(true);
// FotoBinary entity
HasRequired(dependent => dependent.Owner)
.WithRequiredDependent(principal => principal.Content)
.WillCascadeOnDelete(true);
When you use a mapping similar to the one above, all of your Foto
and FotoBinary
rows in the database will share the same primary key (Id
). As long as you know the Id of one, you can use it to query the corresponding row for the other (Owner
or Content
).
Finally, I would at least consider not passing a Lugar
entity into your MVC action. You can instead compose a ViewModel class, like LugarViewModel
. That class can then have an HttpPostedFileBase
property in similar fashion to Karthik's answer. Your controller action can then take the data from the viewmodel and use it to populate a Lugar
entity.