Does anyone have an example of how to store an uploaded document (whether Word or PDF, etc.) in a SQL Server 2008 DB using the Entity Framework?
I think I've figured out the file upload part (see code below) although I'm open to constructive comments.
I used to do a lot of document-storing in older DBs, and as SQL Server 2008 has new data types, can someone suggest which I should be using for my uploaded document (is it still Image)?
Furthermore, as you can see from my code, if I have the uploaded document as a byte array (or please suggest otherwise) how do I pass this to my entity?
Here's what I have so far:
[HttpPost]
public ActionResult Create(HttpPostedFileBase fileUpload)
{
if (fileUpload == null) return View();
if (fileUpload.ContentLength == 0) return View();
// not sure whether this is useful or the method below this
var reader = new StreamReader(fileUpload.InputStream);
foreach (string file in Request.Files)
{
var hpf = Request.Files[file] as HttpPostedFileBase;
if (hpf.ContentLength == 0) continue;
var savedFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.GetFileName(hpf.FileName));
hpf.SaveAs(savedFileName);
var curFile = System.IO.File.Open(file, FileMode.Open);
var fileLength = curFile.Length;
var tempFile = new byte[fileLength];
curFile.Read(tempFile, 0, Convert.ToInt32(fileLength));
var jobFile = new JobFile
{
UploadDate = DateTime.Now,
UploadedBy = User.Identity.Name,
FileName = savedFileName,
ContentType = hpf.ContentType
};
jobFile.FileData =
_jobFileRepository.Save();
}
return RedirectToAction("Index");
}
Any help greatly appreciated.
Assuming you have FileData as type binary.
jobFile.FileData = tempFile.ToArray();
Related
I'm building a MVC controller action which build a zip file containing two files :
Some metadata serialized from the database.
A related content file actually store in an azure storage blob
So far, my controller works fine until a certain file size. Then when the content from azure gets too big I have an out of memory exception certainely related to the fact that i'm writing stuff in the server's memory which is not infinite.
So now I'm wondering which approach should I take ? Write stuff in a temp path on the server or are there other options ?
Here's my controller aciton for the reference :
public async Task<ActionResult> Download(Guid? id)
{
if (id == null)
{
return NotFound();
}
var cIApplication = await _context.CIApplications
.AsNoTracking()
.SingleOrDefaultAsync(m => m.ID == id);
if (cIApplication == null)
{
return NotFound();
}
//Serialize metadata : this will always be small
byte[] metaData = BinSerializer.SerializeToByteArrayAsync<CIApplication>(cIApplication);
//GetFile from Azure blob : This can reach several GB
//StorageManagement is an helper class to manipulate Azure storage objects
StorageManagement storage = new StorageManagement();
byte[] content = await storage.GetBlobToStream("application", $"{cIApplication.ID}.zip");
//Zip It and send it
using (MemoryStream ms = new MemoryStream())
{
using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true))
{
var zipArchiveEntry = archive.CreateEntry($"{cIApplication.ID}.bin", CompressionLevel.Fastest);
using (var zipStream = zipArchiveEntry.Open()) zipStream.Write(metaData, 0, metaData.Length);
zipArchiveEntry = archive.CreateEntry($"{cIApplication.ID}.zip", CompressionLevel.Fastest);
using (var zipStream = zipArchiveEntry.Open()) zipStream.Write(content, 0, content.Length);
}
return File(ms.ToArray(), "application/zip", $"{cIApplication.Publisher} {cIApplication.Name} {cIApplication.Version}.zip");
}
}
I am trying to validate the UK phone number contain in a CSV file before inserting the data in the table. At the moment the if statement is not working when the mobile number is valid the code doesn't jump to the else block. See the code below.
Controller code
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> BulkMEssage(TextMessage messagedetail,
HttpPostedFileBase attachmentcsv,
MobileRecipient messagelink, int ddlshedule, string date)
{
if (ModelState.IsValid)
{
CsvFileDescription csvFileDescription = new CsvFileDescription
{
SeparatorChar = ',',
FirstLineHasColumnNames = true
};
CsvContext csvContext = new CsvContext();
StreamReader streamReader = new
StreamReader(attachmentcsv.InputStream);
IEnumerable<MobileRecipient> list =
csvContext.Read<MobileRecipient>(streamReader,
csvFileDescription);
foreach (var mobilenumber in list)
{
var phoneno = #"/^ (\+44\s ? 7\d{ 3}|\(? 07\d{ 3}\)?)\s ?\d{ 3}\s ?\d{ 3}$/";
if ((!mobilenumber.MobileNumber.Equals(phoneno)))
{
error message Here with the wrong format number
}
else
{
Insert Data in the database
}
}
}
I think I am using the regular expression the wrong way. The column name in my CSV file is called "MobileNumber". Please suggest if you have any better way to do this.
I'm not sure what the problem is but I cant seem to get my program to display the correct information. The requirements for my application are to take a pdf and populate the form fields with information from a database. The problem is that it does not return the information from the database and instead returns the sql generated from entity framework.
(text) SELECT
[Extent1].[Applicant_ID] AS [Applicant_ID]
FROM [dbo].[W4] AS [Extent1]
This is what is displayed in the pdf textbox.
This is my query
public class Query
{
ApplicatoinContext context = new ApplicatoinContext();
public List<W4> GetId()
{
return (from p in context.w4
select new W4 { Applicant_ID = p.Applicant_ID }).ToList();
}
}
My controller
public class ApplicationController : Controller
{
// GET: Application
public ActionResult Index()
{
string template = #"c:\users\carisch\documents\visual studio 2013\Projects\Idea\Idea\fw4.pdf";
string newFile = #"c:\users\carisch\documents\visual studio 2013\Projects\Idea\Idea\Newfw4.pdf";
PdfReader reader = new PdfReader(template);
PdfStamper stamper = new PdfStamper(reader, new FileStream(newFile, FileMode.Create));
AcroFields fields = stamper.AcroFields;
Query num = new Query();
var query = num.GetId();
fields.SetField("f1_15_0_", query.ToString());
stamper.FormFlattening = false;
stamper.Close();
return File(#"c:\users\carisch\documents\visual studio 2013\Projects\Idea\Idea\Newfw4.pdf", "application/pdf");
}
}
I'm pretty new to programming so any help would be greatly appreciated.
I am trying to use the Rotativa component to store (not to show) a copy of the invoice permanently on web server disk. Two questions:
Why I need to specify a controller action? ("Index", in this
case)
How do I write the FileContentResult on local disk without
displaying it?
Thanks.
Here is my code:
[HttpPost]
public ActionResult ValidationDone(FormCollection formCollection, int orderId, bool fromOrderDetails)
{
Order orderValidated = context.Orders.Single(no => no.orderID == orderId);
CommonUtils.SendInvoiceMail(orderValidated.customerID , orderValidated.orderID);
var filePath = Path.Combine(Server.MapPath("/Temp"), orderValidated.invoiceID + ".pdf");
var pdfResult = new ActionAsPdf("Index", new { name = orderValidated.invoiceID }) { FileName = filePath };
var binary = pdfResult.BuildPdf(ControllerContext);
FileContentResult fcr = File(binary, "application/pdf");
// how do I save 'fcr' on disk?
}
You do not need the FileContentResult to create a file. You've got the byte array which can be saved directly to the disk:
var binary = pdfResult.BuildPdf(ControllerContext);
System.IO.File.WriteAllBytes(#"c:\foobar.pdf", binary);
string FileName="YOUR FILE NAME";
//first give a name to file
string Path=Server.MapPath("YourPath in solution"+Filename+".Pdf")
//Give your path and file extention. both are required.
binary[]= YOUR DATA
//Describe your data to be save as file.
System.IO.File.WriteAllBytes(Path, binary);
Thats simple...
I have a working OData controller, which supports all the normal get/put etc.
What I want to do is pass a normal odata $filter string from the client, parse and execute the filter on the server and run some code on the resulting IEnumerable.
I've messed around with ODataQueryContext, ODataQueryOptions, FilterQueryOption etc, but not really got anywhere.
Does anyone have any working examples?
Edit: I've added my function skeleton, just need to fill in the blanks
public HttpResponseMessage GetJobs(string filter)
{
*** How to convert the filter into IQueryable<Job> ***
var queryable = ?????
var settings = new ODataQuerySettings();
var jobs = queryOptions.ApplyTo(querable, settings) as IQueryable<Job>;
CsvSerializer csvSerializer = new CsvSerializer();
string csv = csvSerializer.Serialise(jobs);
string fileName = string.Format("{0} Jobs.csv", filter);
return CreateCsvResponseMessage(csv, fileName);
}
I recently had a scenario where I needed this sort of feature as well. This is what I came up with.
private static IQueryable<T> ApplyODataFilter<T>(IQueryable<T> data, string filterString) where T : class
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<T>(typeof(T).Name);
ODataQueryContext context = new ODataQueryContext(builder.GetEdmModel(), typeof(T), new ODataPath());
ODataQueryOptionParser queryOptionParser = new ODataQueryOptionParser(
context.Model,
context.ElementType,
context.NavigationSource,
new Dictionary<string, string> { { "$filter", filterString } });
FilterQueryOption filter = new FilterQueryOption(filterString, context, queryOptionParser);
IQueryable query2 = filter.ApplyTo(data, new ODataQuerySettings());
return query2.Cast<T>();
}
Try using OData code generator to generate client side code. you can following the following blog:
How to use OData Client Code Generator to generate client-side proxy class
The for the filter, the following is an example:
var q2 = TestClientContext.CreateQuery<Type>("Accounts").Where(acct => acct.Birthday > new DateTimeOffset(new DateTime(2013, 10, 1)));
There are some sample code in the codeplex to show how to do query.
Check this:
https://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/OData/v3/ODataQueryableSample/Program.cs
Update:
There is some sample code in the controller of the sample I gave you.
Write your code as below:
public IQueryable<Order> Get(ODataQueryOptions queryOptions)
{
if (queryOptions.Filter != null)
{
var settings = new ODataQuerySettings();
var filterResult = queryOptions.ApplyTo(OrderList.AsQueryable(), settings) as IQueryable<Order>;
// Use the filter result here.
}
}
Update 2:
You can get the raw string of the filter from ODataQueryOptions.
public IQueryable<Order> Get(ODataQueryOptions queryOptions)
{
string filterString = queryOptions.Filter.RawValue;
// Use the filterString
}
Update 3:
(Note: ODataProperties is an extension method in static class
System.Web.Http.OData.Extensions.HttpRequestMessageExtensions)
public HttpResponseMessage GetJobs(string filter)
{
var context = new ODataQueryContext(Request.ODataProperties().Model, typeof(Job));
var filterQueryOption = new FilterQueryOption(filter, context);
IQueryable<Job> queryable = GetAllJobs();
var settings = new ODataQuerySettings();
var jobs = filterQueryOption.ApplyTo(queryable, settings) as IQueryable<Job>;
CsvSerializer csvSerializer = new CsvSerializer();
string csv = csvSerializer.Serialise(jobs);
string fileName = string.Format("{0} Jobs.csv", filter);
return CreateCsvResponseMessage(csv, fileName);
}