Pass the value to database in asp.net web api - c#

Am trying to save the images to the database using the asp.net webapi. In this controller am saving the image into my /Content/Banner/ Folder.
[HttpPost]
[Route("PostBanner")]
[AllowAnonymous]
public HttpResponseMessage PostBannerImage()
{
Dictionary<string, object> dict = new Dictionary<string, object>();
try
{
var httpRequest = HttpContext.Current.Request;
foreach (string file in httpRequest.Files)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created);
var postedFile = httpRequest.Files[file];
if (postedFile != null && postedFile.ContentLength > 0)
{
int MaxContentLength = 1024 * 1024 * 1; //Size = 1 MB
IList<string> AllowedFileExtensions = new List<string> { ".jpg", ".gif", ".png" };
var ext = postedFile.FileName.Substring(postedFile.FileName.LastIndexOf('.'));
var extension = ext.ToLower();
if (!AllowedFileExtensions.Contains(extension))
{
var message = string.Format("Please Upload image of type .jpg,.gif,.png.");
dict.Add("error", message);
return Request.CreateResponse(HttpStatusCode.BadRequest, dict);
}
else if (postedFile.ContentLength > MaxContentLength)
{
var message = string.Format("Please Upload a file upto 1 mb.");
dict.Add("error", message);
return Request.CreateResponse(HttpStatusCode.BadRequest, dict);
}
else
{
var filePath = HttpContext.Current.Server.MapPath("~/Content/Banner/" + postedFile.FileName + extension);
postedFile.SaveAs(filePath);
}
}
var message1 = string.Format("Image Updated Successfully.");
return Request.CreateErrorResponse(HttpStatusCode.Created, message1); ;
}
var res = string.Format("Please Upload a image.");
dict.Add("error", res);
return Request.CreateResponse(HttpStatusCode.NotFound, dict);
}
catch (Exception ex)
{
var res = string.Format("some Message");
dict.Add("error", res);
return Request.CreateResponse(HttpStatusCode.NotFound, dict);
}
}
Now what i need to send this filePath to database. I know i just need to pass this file path to the following service controller. But i dont know how to pass it. could anyone help me to solve this problem.
This Is my services.cs
public async Task<int?> Addbanner(DisplayBannersDto dto)
{
try
{
var d = _dbContext.Banners
.FirstOrDefault();
d.Banner_Description = dto.Description;
d.Banner_Location = dto.Location;
//mark entry as modifed
_dbContext.Entry(d).State = EntityState.Modified;
await _dbContext.SaveChangesAsync();
return d.Banner_Id;
}
catch (Exception ex)
{
throw ex;
}
}
This is my controller
[HttpPost]
[Route("AddBanner")]
public async Task<IHttpActionResult> AddBanner(DisplayBannersDto dto)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
int? result = await _service.Addbanner(dto);
return Ok();
}

Change your else condition like below:
else
{
var filePath = HttpContext.Current.Server.MapPath("~/Content/Banner/" + postedFile.FileName + extension);
postedFile.SaveAs(filePath);
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.Created,
Content = new StringContent(filePath, Encoding.UTF8, "application/json")
};
}
Now, you have the filepath in the content of the API response.
and use that response like :
var displayBannersDto = new DisplayBannersDto();
displayBannersDto.Banner_Location = response.Content.ToString();
then call your AddBanner() API with displayBannersDto as the dto.

Related

InvalidOperationException in Memory Streams

I am trying to upload an image to cloudinary cloud. The file converts fine to memory stream but when I try to call upload method of cloudinary to upload the image, I get InvlalidOperationException. What I think is, there is something wrong with converting file to stream.See the image showing error
[HttpPost]
public async Task<IActionResult> AddPhotoForUser(int userId, [FromForm] AddPhotoDto addPhotoDto)
{
try
{
if (userId != int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value))
{
return Unauthorized();
}
var userFromRepo = await _datingRepository.GetUser(userId);
var file = addPhotoDto.File;
var uploadResult = new ImageUploadResult();
if (file.Length > 0)
{
using (var stream = file.OpenReadStream())
{
var uploadParams = new ImageUploadParams()
{
File = new FileDescription(file.Name, stream),
Transformation = new Transformation()
.Width(500).Height(500).Crop("fill").Gravity("face")
};
uploadResult = _cloudinary.Upload(uploadParams);
}
}
addPhotoDto.Url = uploadResult.Url.ToString();
addPhotoDto.PublicId = uploadResult.PublicId;
var photo = _mapper.Map<Photo>(addPhotoDto);
if (!userFromRepo.Photos.Any(p => p.IsMain))
{
photo.IsMain = true;
}
userFromRepo.Photos.Add(photo);
if (await _datingRepository.SaveAll())
{
var photoToReturn = _mapper.Map<ReturnPhotoDto>(photo);
return CreatedAtRoute("GetPhoto", new { id = photo.Id }, photoToReturn);
}
return BadRequest("Could not add photo");
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
Can you please share why do you use open stream? You can try:
var imageuploadParams = new ImageUploadParams () {
File = new FileDescription (#"https://res.cloudinary.com/demo/image/upload/v1561532539/sample.jpg"),
PublicId = "myimage",
Transformation = new Transformation().Width(500).Height(500).Crop("fill").Gravity("face")
};
var ImageuploadResult = cloudinary.Upload (imageuploadParams);

Incorrect behavior when trying to simultaneously download multiple PDFs

I have a list of reports page. I have a download button for each report. If I click 4-5 reports download button I only get the last one downloaded. Below you can see my code
public async Task<ActionResult> Download(ReportPage currentPage, string id)
{
var token = RystadIdentity.Current.AuthenticatedUser.Token;
try
{
DocumentRequestInput documentRequestInput = new DocumentRequestInput(int.Parse(id), 2);
documentRequestInput.Add(token);
}
catch
{ }
Report report = await RystadGlobal.api.GetReport(token, int.Parse(id));
string ext = Path.GetExtension(report.fileName);
byte[] byteArray = await RystadGlobal.api.DownloadReport(token, report.Id);
if (ext.ToLower() == ".pdf")
{
var name = RystadIdentity.Current.AuthenticatedUser.UserInfo.name;
var company = RystadIdentity.Current.AuthenticatedUser.UserInfo.company;
try
{
byteArray = PdfWatermarker.Watermark(byteArray, name, company);
}
catch (Exception ex)
{
//Ignore if failed and give the user the pdf anyway
}
}
return File(byteArray, System.Net.Mime.MediaTypeNames.Application.Octet, report.fileName);
}
public async Task<byte[]> DownloadReport(Token token, int reportId)
{
clientForDownloading.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(token.token_type, token.access_token);
var result = await clientForDownloading.GetAsync("api/" + ApiVersion + "/LibraryDocument/" + reportId + "/download");
if (!result.IsSuccessStatusCode)
throw new ApiException("Could not download the report");
var contentBytes = await result.Content.ReadAsByteArrayAsync();
return SevenZipHelper.Decompress(contentBytes);
}
public async Task<Report> GetReport(Token token, int reportId)
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(token.token_type, token.access_token);
var result = await client.GetAsync("api/" + ApiVersion + "/LibraryDocument/" + reportId);
if (!result.IsSuccessStatusCode)
throw new ApiException("Could not get report");
Report report = await result.Content.ReadAsAsync<Report>();
return report;
}
Does anyone see the issue which I am missing?
You can try to do it Synchronously like so:
public ActionResult Download(ReportPage currentPage, string id)
{
var token = RystadIdentity.Current.AuthenticatedUser.Token;
try
{
DocumentRequestInput documentRequestInput = new DocumentRequestInput(int.Parse(id), 2);
documentRequestInput.Add(token);
}
catch
{ }
Report report = RystadGlobal.api.GetReport(token, int.Parse(id)).Result;
string ext = Path.GetExtension(report.fileName);
byte[] byteArray = RystadGlobal.api.DownloadReport(token, report.Id).Result;
if (ext.ToLower() == ".pdf")
{
var name = RystadIdentity.Current.AuthenticatedUser.UserInfo.name;
var company = RystadIdentity.Current.AuthenticatedUser.UserInfo.company;
try
{
byteArray = PdfWatermarker.Watermark(byteArray, name, company);
}
catch (Exception ex)
{
//Ignore if failed and give the user the pdf anyway
}
}
return File(byteArray, System.Net.Mime.MediaTypeNames.Application.Octet, report.fileName);
}
The other problem might be in this method:
RystadGlobal.api.GetReport(token, int.Parse(id))
I do not know that this method looks like inside
EDIT
Try creating new instances of your clients in the methods you added in your question:
public async Task<byte[]> DownloadReport(Token token, int reportId)
{
using(var clientForDL = new System.Net.Http.HttpClient())
{
clientForDL.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(token.token_type, token.access_token);
var result = await clientForDL.GetAsync("api/" + ApiVersion + "/LibraryDocument/" + reportId + "/download");
if (!result.IsSuccessStatusCode)
throw new ApiException("Could not download the report");
var contentBytes = await result.Content.ReadAsByteArrayAsync();
return SevenZipHelper.Decompress(contentBytes);
}
}
public async Task<Report> GetReport(Token token, int reportId)
{
using(var clientForGet = new System.Net.Http.HttpClient())
{
clientForGet.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(token.token_type, token.access_token);
var result = await clientForGet.GetAsync("api/" + ApiVersion + "/LibraryDocument/" + reportId);
if (!result.IsSuccessStatusCode)
throw new ApiException("Could not get report");
Report report = await result.Content.ReadAsAsync<Report>();
return report;
}
}

Download file on button click

I have a application where a button click needs to download a text log file. I wrote the backend API, but am not able to connect it from the frontend button click. Working on Angular 2 and C#. What changes do I need to make to component.ts file?
Button code:
<div class="col-lg-4"> <button type="button" class="btn btn-info pull-right" [hidden]="!dbtn" (click)="GetMigrationLog()" id="downloadLog" translate>Download Log</button> </div>
Here is my backend api code:
[Route("GetMigrationLog")]
public IHttpActionResult GetMigrationLog()
{
try
{
IDBMigrationDataBo data = _serviceLocator.Resolve<IDBMigrationDataBo>();
var result = data.GetMigrationLog();
string logFileName = string.Format("Migration_{0}.txt", DateTime.Now.ToString("dd-MM-yyyy"));
return StreamResponse(result, logFileName);
}
catch (Exception ex)
{
logger.Error(ex.Message);
return this.HandleError(ex);
}
}
I've done somthing similar .. it's a little bit difficult .. i share my experience and my code with you .. hope it helps you!!
in your html
Download Log
in your ts:
saveFile(id: string, name: string) {
this._orderService.DownloadRicetta(id, name).then((result) => {
this._toaster.pop('success', 'Download', 'Ricetta Scaricata con Successo');
}).catch((err) => {
this._toaster.pop('error', 'Download', 'Errore nel Download della Ricetta!')
console.log(err);
});
}
in your service file:
first of all import a package (installed with npm i --save file-saver #types/file-saver)
import * as FileSaver from 'file-saver';
then write your method like this:
public async DownloadRicetta(id: string, name: string): Promise<Blob> {
return new Promise<Blob>((resolve, reject) => {
const headers = new HttpHeaders();
headers.append('Accept', 'text/plain'); //just check the type you need
this._http.get(environment.API_URL + `Order/${id}/Download/Ricetta`, { headers: headers, responseType: "blob", observe: 'response' })
.subscribe(response => {
try {
let blob = this.saveToFileSystem(response, name);
resolve(blob);
} catch (error) {
reject(error);
}
});
});
}
private saveToFileSystem(response, name: string): Blob {
const contentDispositionHeader: string = response.headers.get('Content-Disposition');
//for get original filename
const parts: string[] = contentDispositionHeader.split(';');
const filename = parts[1].trim().split('=')[1].trim();
//get extension of the file
const parts2: string[] = contentDispositionHeader.split('.');
let ext = parts2[1];
ext = ext.replace('"', '')
//set mimetype
let mimeType = Utils.extToMimeType(ext);
const blob = new Blob([response.body], { type: mimeType });
FileSaver.saveAs(blob, name + '_ricetta.' + ext);
return blob;
}
file UTILS.ts:
export default class Utils {
static extToMimeType(ext: string) {
switch (ext) {
case "pdf":
return "application/pdf";
case "jpg":
return "image/jpg";
case "png":
return "image/png";
case "txt":
return "text/plain";
default:
return "";
}
}
}
AND ALSO BACK END (ASP.NET WEBAPI 2 ):
[HttpGet]
[Route("api/Order/{id}/Download/Ricetta")]
public async Task<HttpResponseMessage> GetBookForHRM([FromUri] string id)
{
try
{
if (string.IsNullOrEmpty(id)) return new HttpResponseMessage { StatusCode = HttpStatusCode.BadRequest };
var order = await _orderService.FindAsync(xx => xx.Id == id);
if (order == null) return new HttpResponseMessage { StatusCode = HttpStatusCode.BadRequest };
if (string.IsNullOrEmpty(order.RicettaUrl)) return new HttpResponseMessage { StatusCode = HttpStatusCode.BadRequest };
var user = await _aspNetService.FindAsync(xx => xx.Id == order.IdUser);
if (user == null) return new HttpResponseMessage { StatusCode = HttpStatusCode.BadRequest };
var fileWithPath = $#"{user.GetUserRicettaDirectory()}/{order.RicettaUrl}";
//converting Pdf file into bytes array
var dataBytes = File.ReadAllBytes(fileWithPath);
//adding bytes to memory stream
var dataStream = new MemoryStream(dataBytes);
HttpResponseMessage httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK);
httpResponseMessage.Content = new StreamContent(dataStream);
httpResponseMessage.Content.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
httpResponseMessage.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
{
FileName = order.RicettaUrl.Trim()
};
httpResponseMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
return httpResponseMessage;
}
catch (Exception ex)
{
_logger.LogException(ex);
throw;
}
}

How do I detect canceled asynchronous post

I use the following code to upload a file and form data asynchronous. What do I need to change in order to detect if the transfer has been cancelled or interrupted and then take proper action?
[HttpPost]
public async Task<object> UploadFile()
{
if (!Request.Content.IsMimeMultipartContent("form-data"))
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.UnsupportedMediaType));
}
var streamProvider = new MultipartFormDataStreamProvider(HttpContext.Current.Server.MapPath("~/App_Data/Temp/"));
try
{
var filesReadToProvider = await Request.Content.ReadAsMultipartAsync(streamProvider);
var paramName = "formInput";
var formStreamToRead = filesReadToProvider.Contents.First(x => x.Headers.ContentDisposition.Name == $"\"{formInput}\"");
var formInput = await formStreamToRead.ReadAsStringAsync();
foreach (var fileData in streamProvider.FileData)
{
var fileName = "";
if (string.IsNullOrEmpty(fileData.Headers.ContentDisposition.FileName))
{
fileName = Guid.NewGuid().ToString();
}
fileName = fileData.Headers.ContentDisposition.FileName;
if (fileName.StartsWith("\"") && fileName.EndsWith("\""))
{
fileName = fileName.Trim('"');
}
if (fileName.Contains(#"/") || fileName.Contains(#"\"))
{
fileName = Path.GetFileName(fileName);
}
File.Move(fileData.LocalFileName, Path.Combine(HttpContext.Current.Server.MapPath("~/App_Data/"), Path.GetDirectoryName(fileName) + Guid.NewGuid() + Path.GetExtension(fileName)));
}
return Request.CreateResponse(HttpStatusCode.OK);
}
catch (Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}

Get a black/no image with asp.net web api

I'am posting an image from a console application to a asp.net web api. I'am getting a file in the folder but the image is black (no image). Do I have something wrong in my code?
public class UploadController : ApiController
{
[System.Web.Mvc.HttpPost]
public string Upload()
{
var request = HttpContext.Current.Request;
var filePath = Path.Combine(HttpContext.Current.Server.MapPath("~/Uploads/"), request.Headers["filename"]);
try
{
using (var fs = new System.IO.FileStream(filePath, System.IO.FileMode.Create))
{
request.InputStream.CopyTo(fs);
}
}
catch (Exception e)
{
return e.Message;
}
return "uploaded";
}
}
Edit
My console app
http://pastebin.com/VsnDMYpb
try this. This works for me. I used this for multiple file upload
var httpRequest = HttpContext.Current.Request;
foreach (string file in httpRequest.Files)
{
var postedFile = httpRequest.Files[file];
var filePath = HttpContext.Current.Server.MapPath("~/Uploads/" + postedFile.FileName);
postedFile.SaveAs(filePath);
}
Use Request.Content.ReadAsMultipartAsync
public Task<IQueryable<HDFile>> Post()
{
try
{
var uploadFolderPath = HostingEnvironment.MapPath("~/App_Data/" + UploadFolder);
log.Debug(uploadFolderPath);
if (Request.Content.IsMimeMultipartContent())
{
var streamProvider = new WithExtensionMultipartFormDataStreamProvider(uploadFolderPath);
var task = Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith<IQueryable<HDFile>>(t =>
{
if (t.IsFaulted || t.IsCanceled)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
var fileInfo = streamProvider.FileData.Select(i =>
{
var info = new FileInfo(i.LocalFileName);
return new HDFile(info.Name, Request.RequestUri.AbsoluteUri + "?filename=" + info.Name, (info.Length / 1024).ToString());
});
return fileInfo.AsQueryable();
});
return task;
}
else
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
}
}
catch (Exception ex)
{
log.Error(ex);
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.BadRequest, ex.Message));
}
}
The code I get from this post

Categories