How to Post a file using Fiddler to WebAPI using C#? - file-upload

I am new to ASP.NET Web API. I have a sample FileUpload web api (from some site) to upload files to the server. But, don't know how to test it using Fiddler.
http://localhost:54208/myapi/api/webapi/FileUpload
On test.aspx page: Following works fine.
I want to know how to use this API using Fiddler?
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form enctype="multipart/form-data" method="post" action="http://localhost:54208/myapi/api/webapi/FileUpload" id="ajaxUploadForm" novalidate="novalidate">
<fieldset>
<legend>Upload Form</legend>
<ol>
<li>
<label>Description </label>
<input type="text" style="width:317px" name="description" id="description">
</li>
<li>
<label>upload </label>
<input type="file" id="fileInput" name="fileInput" multiple>
</li>
<li>
<input type="submit" value="Upload" id="ajaxUploadButton" class="btn">
</li>
</ol>
</fieldset>
</form>
</body>
</html>
public async Task<HttpResponseMessage> FileUpload()
{
// Check whether the POST operation is MultiPart?
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
// Prepare CustomMultipartFormDataStreamProvider in which our multipart form
// data will be loaded.
//string fileSaveLocation = HttpContext.Current.Server.MapPath("~/App_Data");
string fileSaveLocation = HttpContext.Current.Server.MapPath("~/UploadedFiles");
CustomMultipartFormDataStreamProvider provider = new CustomMultipartFormDataStreamProvider(fileSaveLocation);
List<string> files = new List<string>();
try
{
// Read all contents of multipart message into CustomMultipartFormDataStreamProvider.
await Request.Content.ReadAsMultipartAsync(provider);
foreach (MultipartFileData file in provider.FileData)
{
files.Add(Path.GetFileName(file.LocalFileName));
}
// Send OK Response along with saved file names to the client.
return Request.CreateResponse(HttpStatusCode.OK, files);
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
// We implement MultipartFormDataStreamProvider to override the filename of File which
// will be stored on server, or else the default name will be of the format like Body-
// Part_{GUID}. In the following implementation we simply get the FileName from
// ContentDisposition Header of the Request Body.
public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
{
public CustomMultipartFormDataStreamProvider(string path) : base(path) { }
public override string GetLocalFileName(HttpContentHeaders headers)
{
return headers.ContentDisposition.FileName.Replace("\"", string.Empty);
}
}
Help Appreciated!

Go to fiddler, select post type, give your local web api url.
In request body just upload file and execute, it will go to webapi method directly.
Controller method should be [HttpPost]

Related

How to access C# application from jQuery in Razor Pages?

Environment: ASP.NET Core 6.0, Razor Pages
Authentication:
The users log in, and their access token (Bearer jwt) is stored in Session storage.
The problem:
I want to display an array of objects that a request gives me. These objects have a part that has to be queried separately for each of them from the backend. For presentation purposes, I want to display them on the same page, but I do not want to query them before the page loads, because that is slow.
So the question is, how to access HttpClient (or the service that uses HttpClient and handles requests) from jQuery? My current idea is to pass the Bearer token to the partials, that way it can be accessed from them, and to go with an XMLHttpRequest. Are there any better solutions to populate these dropdowns on demand?
Index.cshtml
#page
#model IndexModel
#foreach (var part in Model.Parts)
{
<partial name="_PartPartial" model="new { PartData = part, Id = #Model.Id, Bearer = Bearer }" />
}
Index.cshtml.cs
public class IndexModel : PageModel
{
public List<PartModel> Parts;
public string Id;
public async Task<IActionResult> OnGetAsync(string Id)
{
// Query Parts from endpoint...
return Page();
}
}
_PartPartial.cshtml
#model dynamic
<div class="card">
<div class="card-header">
<button type="button" class="btn" data-bs-toggle="collapse" data-bs-target="#partContent_#Model.PartData.partId"
aria-expanded="false" aria-controls="partContent_#Model.PartData.partId" data-id="#Model.PartData.partId" onclick="queryInnerData(this);">
#Model.PartData.DisplayName
</button>
</div>
<div class="collapse" id="partContent_#Model.PartData.partId">
<div class="card card-body">
<div id="innerData_#Model.PartData.partId"></div>
</div>
</div>
</div>
<script type="text/javascript">
function queryInnerData(sender)
{
// This is the part where I am stuck. How do I access the Bearer
}
</script>
I have tried creating a page that does an HttpRequest and returns a JsonResult in its OnGet method. This works, but exposes the raw data to the outside world as well, so I would rather not go with this solution.

Ajax success method not firing

I'm using ASP.NET Core 2 MVC and I have a Controller with a Post action method as such:
[HttpPost]
[Produces("application/json")]
public async Task<IActionResult> PostObject([FromForm] ObjectViewModel bjectViewModel)
{
if (!ModelState.IsValid) return BadRequest(ModelState);
//EF code
return Ok(object);
}
My view has the following code:
//View code...
<form asp-action="PostObject" data-ajax="true" data-ajax-method="POST" data-ajax-success="OnSuccess" data-ajax-failure="OnFailure">
#Html.HiddenFor(x => x.VolumeID)
<label asp-for="EAN" class="control-label"></label>
<input asp-for="EAN" id="TextBoxEAN" class="form-control" value="" maxlength="13" autofocus />
<span asp-validation-for="EAN" class="text-danger"></span>
</form>
//More view code...
//This contais ajax stuff
#section Scripts {#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script>
function OnSuccess(result) {
console.log(result);
}
function OnFailure(result) {
alert(result);
}
</script>
I can perform the POST action correctly, but instead of executing the OnSuccess method, it just displays the returned JSON object.
I think this has something to do with referencing ajax-unobtrusive, but I think that is taken care of automatically.
Can someone point me in the right direction?

MVC post method

I have two Views with two different post method in different Controllers. Both methods are used to export data to an Excel file.
Here is my code structure:
[System.Web.Mvc.HttpPost]
public ActionResult upload(HttpPostedFileBase file)
{
// code for this action
ExportToExcel(dd); // export from dataset
}
public void ExportToExcel(DataSet dd)
{
// Code to export
}
My View page code looks like:
<html>
<body>
#using (#Html.BeginForm("upload", "Test", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
<input type="file" name="file" id="files" multiple="multiple" />
<input type="submit" class="btn btn-lg btn-primary" value="Export Excel" name="submit" />
}
</body>
</html>
I have a second post method in another controller that looks basically the same as the above code, with only slight differences.
How can I merge the two post methods into one, and use to export?

Html Form - route is wrong

I am using the FileUpload sample from the asp.net tutorials. When I build it as a stand alone, it works fine. However, whenever I try to add that functionality to a new MVC4 website, the routing is wrong. I'm probably not explaining this well, so here is the code:
[HttpPost]
public async Task<HttpResponseMessage> PostFile()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
try
{
var sb = new StringBuilder(); // Holds the response body
// Read the form data and return an async task.
await Request.Content.ReadAsMultipartAsync(provider);
// This illustrates how to get the form data.
foreach(var key in provider.FormData.AllKeys)
{
var strings = provider.FormData.GetValues(key);
if (strings != null) foreach(var val in strings)
{
sb.Append(string.Format("{0}: {1}\n", key, val));
}
}
// This illustrates how to get the file names for uploaded files.
foreach(var file in provider.FileData)
{
var fileInfo = new FileInfo(file.LocalFileName);
sb.Append(string.Format("Uploaded file: {0} ({1} bytes)\n", fileInfo.Name, fileInfo.Length));
}
return new HttpResponseMessage
{
Content = new StringContent(sb.ToString())
};
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
Here is the page I'm using:
<div style="height:400px;">
<h3>File Upload</h3>
<form name="trip_search" method="post" enctype="multipart/form-data" action="api/upload">
<div>
<input type="radio" name="trip" value="round-trip"/>
Round-Trip
</div>
<div>
<input type="radio" name="trip" value="one-way"/>
One-Way
</div>
<div>
<input type="checkbox" name="options" value="nonstop" />
Only show non-stop flights
</div>
<div>
<input type="checkbox" name="options" value="airports" />
Compare nearby airports
</div>
<div>
<input type="checkbox" name="options" value="dates" />
My travel dates are flexible
</div>
<div>
<label for="seat">Seating Preference</label>
<select name="seat">
<option value="aisle">Aisle</option>
<option value="window">Window</option>
<option value="center">Center</option>
<option value="none">No Preference</option>
</select>
</div>
<div>
<input type="submit" value="Submit" />
</div>
</form>
When I directly navigate to localhost:13927api/upload I see a response from the web api method. I've got the DefaultApi route registered in my WebApiConfig.
But when I'm on the page localhost/Home/About and I click on the submit button, it attempts to go to localhost/Home/api/upload - which does not exist.
What am I missing?
EDIT
The suggestion by Mario fixed my issue. The action method on my form was not relative to the root.
action="api/upload" vs. action="/api/upload"
That fixes my problem.
A bit of elaboration on the issue:
When you are in the default path (say yoursite/Home/Index -> if that is your default), then the action="api/myaction" will work because the current path is still seen as the root of the website. However, once you actually navigate to a path (say yoursite/Home/About), the current path is now under "Home" and so my missing "/" naturally was relative to my current path rather than the root. This is why the samples work without the leading "/", because the view in question is the default view.
Added the answer, if that can help others too:
Your form action="api/upload" is not relative to the root. Try action="/api/upload" or use one of the helpers to specify the route.

Multiple upload file with PlayFramework

I'm trying to upload multiple files at once with Play Framework, but I always get the first image for each uploaded. Here's a concrete case :
The HTML :
<form method="post" action="/upload" enctype="multipart/form-data">
<input type="file" name="image" />
<input type="file" name="image" />
<input type="file" name="image" />
<input type="file" name="image" />
<input type="submit" name="submit" value="Send images" />
</form>
The controller :
public static void upload() {
File[] images = params.get("image", File[].class);
for (File f : images) {
Logger.info (f.getName());
}
}
If I upload image1.jpg, image2.jpg, image3.jpg & image4.jpg, the Logger.info on the console will display :
image1.jpg
image1.jpg
image1.jpg
image1.jpg
The other images won't be used.
I tried with List<File> instead of File[] but it doesn't work neither.
I also saw there is kind the same question here on SO (here), that use this as an answer :
List<Upload> files = (List<Upload>) request.args.get("__UPLOADS");
But it doesn't work in the v1.2.4 of Play!.
I'm using Play v1.2.4.
Thank you really much for your help!
Well, I have opened a ticket at Play! Framework because it seems to be problem, and apparently, I'm not the only one to have this behavior.
I tested with the new 1.2.5, and the problem is fixed, at least with the solution I gave on the question :
public static void upload() {
File[] images = params.get("image", File[].class);
for (File f : images) {
Logger.info (f.getName());
}
}
Note: I'm using Java 7!
Use the automatic binding instead of looking in the params:
public class Application extends Controller {
public static void index() {
render();
}
public static void upload(File[] files)
{
for (File file : files)
{
Logger.info(file.getName());
}
index();
}
}
The view template:
#{extends 'main.html' /}
#{set title:'Home' /}
#{form #upload(), enctype:'multipart/form-data'}
<input type="file" name="files" />
<input type="file" name="files" />
<input type="file" name="files" />
<input type="submit" value="Send it..." />
#{/}
multi file upload with play?
public static void overviewsubmit(File fake) {
List<Upload> files = (List<Upload>) request.args.get("__UPLOADS");
for(Upload file: files) {
Logger.info("Size = %d", file.getSize());
}
}
Without the File fake argument the method will not handle multipart/form-data and you'll get an empty request.args array. If anyone knows the play/standard annotation for it, let me know :)