Web API - How to upload excel file with request parameters using Fiddler - asp.net-web-api

I am uploading excel file on server through Web Api. I need to pass some parameters along with the file.
But when I am using fiddler i can able to get either Request parameters or file only, but i need both things in my web API controller.
Method Type: Post
URL : http://localhost/MP.Services/api/catalog/file/upload/
Request Header-
User-Agent: Fiddler
Host: localhost
Content-Length: 74
Content-Type: application/json; charset=utf
Request Body-
{
"CatalogCode":"1",
"Action":"1",
"Entity":"1",
"UploadedBy":"1"
}
Above is my Normal way to pass request parameter, I tried to upload the excel file in fiddler from 'Upload file' option along with above request, but when file gets uploaded request header and request body gets change.
When I run this then I will not able to get the Request Parameters to my web API controller.
My Controller Action Code-
[HttpPost]
public async Task<HttpResponseMessage> UploadCatalogExcel(CatalogUploadRequest catalogUploadRequest)
{
if (catalogUploadRequest == null)
return CreateResponse(HttpStatusCode.NotAcceptable, ControllerErrorCodeConstants.RequestIsInvalid, "Invalid request");
if (!ModelState.IsValid) return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
if (!Request.Content.IsMimeMultipartContent())
return Request.CreateResponse(HttpStatusCode.UnsupportedMediaType, "Uploading file is mandatory");
try
{
//Request to BL Mapping
var catalogUploadExcelBi = CatalogUploadMapping.UploadCatalogExcelRequestToBiMap(catalogUploadRequest);
var CatalogInfo = _catalogUploadBi.GetSampleCatalogExcel(catalogUploadExcelBi.CatalogCode);
string uploadPath = HttpContext.Current.Server.MapPath("~/App_Data");
uploadPath = uploadPath + "\\Upload\\" + CatalogInfo.SellerAccountId + "_" + CatalogInfo.SellerAccountName + "\\" + DateTime.Now.Year.ToString() + "_" + CatalogInfo.CatalogCode; // Physical File Location
string currentTime = Regex.Replace(DateTime.Now.ToString(), "[^0-9]+", "");
string name = catalogUploadExcelBi.CatalogCode + "_" + currentTime + ".xlsx"; // File Name
catalogUploadExcelBi.FileName = "aa";
catalogUploadExcelBi.FilePath = uploadPath;
bool exists = System.IO.Directory.Exists(uploadPath);
if (!exists)
System.IO.Directory.CreateDirectory(uploadPath);
MyStreamProvider streamProvider = new MyStreamProvider(uploadPath);
await Request.Content.ReadAsMultipartAsync(streamProvider);
var response = _catalogUploadBi.LogUploadCatalogExcel(catalogUploadExcelBi);
if (response.ServerErrors != null && response.ServerErrors.Count != 0)
{
response.ServerErrors = response.ServerErrors;
return Request.CreateResponse(HttpStatusCode.BadRequest, response.ServerErrors);
}
return Request.CreateResponse(HttpStatusCode.OK, "File uploaded successfully");
}
catch (Exception ex)
{
var error = _errorManager.GetCustomeError(ex.GetType().ToString());
return error != null && !string.IsNullOrWhiteSpace(error.ErrorCode) && !string.IsNullOrWhiteSpace(error.ErrorMessage)
? Request.CreateResponse(string.Format("Exception Occured! Error code : {0} Error Message : {1}", error.ErrorCode,
error.ErrorMessage)) : Request.CreateResponse(string.Format("Upload file method Exception Occured!"));
}
}

Related

MinIO Uploading a file with name containing especial characters issues an HTTP 403 Forbidden

Uploading an object from a .net webclient to MinIO where the object contains special characters in the name issues an HTTP 403.
This object fails: old_me_bold+19(1).jpg
This object is ok: old_me_bold19.jpg
The message is:
The request signature we calculated does not match the signature you provided. Check your key and signing method.
What is breaking in MinIO?
Encoding the Url did not work either. I also tried PresignedPutObjectAsync to create a tmp Url already signed then I did a PUT using an HttpClient with the same result. To test that this way would work, I removed the special characters from the name of the file and the client was able to send the file to MinIO.
This code fails:
public async System.Threading.Tasks.Task PutAttachementAsync(
Attachment attachment,
string bukectName,
string objectName,
string attachmentType = "application/octet-stream")
{
using (HttpClient client = new HttpClient())
{
var minioClient = GetMinioClient();
client.BaseAddress = new Uri(Config.Instance.GetConfig("MinIOURL"));
var tempFileName = CreateAttachmentTempFile(attachment, out bool virusScanResult);
if (!virusScanResult)
return;
using (FileStream str = new FileStream(tempFileName.FileAttachmentPath, FileMode.Open))
{
try
{
String signedTMPUrl = await minioClient.PresignedPutObjectAsync(bukectName, objectName, 60 * 60 * 24);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(attachmentType));
HttpResponseMessage response = await client.PutAsync(signedTMPUrl, new StreamContent(str));
if (response.IsSuccessStatusCode)
{
Log.InfoFormat("Request Message Information:- \n\n" + response.RequestMessage + "\n");
Log.InfoFormat("Response Message Header \n\n" + response.Content.Headers + "\n");
}
else
{
Log.InfoFormat("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
}
}
catch (MinioException e)
{
Log.Error("Error occurred: " + e.Message);
}
}
}
}
That code is running from an ASP.Net application hosted in IIS. I wonder if IIS is injecting something into the header before the message goes to MinIO.
Any other file that I send to MinIO, if the name does not contain characters such as (), then the upload works always.

How to wait for request to finish in Jmeter

I am currently new to Jmeter, and trying to create a Jmeter script to test how long a request takes to process and complete.
a) Authenticate using Token - Complete
b) Post Request - Complete - Returns 200
c) Get Request - Partially Completed
C: I am Trying to get be able to monitor this request to find out when its either completed failed etc.
I have created the Http Request Sample with a Get Request
I am able to get the Request 200 but it doesn't wait for completion
So running this in a console app, it waits for a certain time checking for status....
Is there a way to possibly write a code similar to the C# code in bean shell or groovy to wait. I was reading about while controller as well...
var result = WaitForBuildToComplete(dest, requestData, token, timeout);
static string GetStatus(string path, Token token)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(path);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "GET";
AddToken(token, httpWebRequest);
WebResponse response = httpWebRequest.GetResponse();
string responseFromServer = "";
using (Stream dataStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(dataStream);
responseFromServer = reader.ReadToEnd();
}
// Close the response.
response.Close();
return responseFromServer;
}
static int WaitForBuildToComplete(string dest, RequestData requestData, Token token, int
timeout)
{
if (timeout <= 0) return 0;
var path = $"{ConfigurationManager.AppSettings[dest]}/policy?id={requestData.id}";
var startTime = DateTime.Now;
do
{
var status = GetStatus(path, token);
var msg = JsonConvert.DeserializeObject<string>(status);
var requestStatus = JsonConvert.DeserializeObject<RequestStatus>(msg);
if (!string.IsNullOrEmpty(requestStatus.DllUrl))
{
Console.WriteLine($"\nResult dll at: {requestStatus.DllUrl}");
return 0;
}
if (requestStatus.Status.ToUpper() == "FAILED")
{
Console.WriteLine($"\nFAILED");
Console.WriteLine(requestStatus.Message);
return -1;
}
if (requestStatus.Status.ToUpper() == "FAILED_DATA_ERROR")
{
Console.WriteLine($"\nFAILED_DATA_ERROR");
Console.WriteLine(requestStatus.Message);
return -1;
}
if (requestStatus.Status.ToUpper() == "NOT_NEEDED")
{
Console.WriteLine($"\nNOT_NEEDED");
Console.WriteLine(requestStatus.Message);
return -1;
}
Console.Write(".");
System.Threading.Thread.Sleep(1000);
} while ((DateTime.Now - startTime).TotalSeconds < timeout);
Console.WriteLine("Time out waiting for dll.");
return -1;
}
I started by looking at JSR223 Sampler but wanted to see if there is a better and easier way to accomplish this.
List<String> sendRequest(String url, String method, Map<String,Object> body) {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(2000)
.setSocketTimeout(3000)
.build();
StringEntity entity = new StringEntity(new Gson().toJson(body), "UTF-8");
HttpUriRequest request = RequestBuilder.create(method)
.setConfig(requestConfig)
.setUri(url)
.setHeader(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8")
.setEntity(entity)
.build();
String req = "REQUEST:" + "\n" + request.getRequestLine() + "\n" + "Headers: " +
request.getAllHeaders() + "\n" + EntityUtils.toString(entity) + "\n";
HttpClientBuilder.create().build().withCloseable {httpClient ->
httpClient.execute(request).withCloseable {response ->
String res = "RESPONSE:" + "\n" + response.getStatusLine() + "\n" + "Headers: " +
response.getAllHeaders() + "\n" +
(response.getEntity() != null ? EntityUtils.toString(response.getEntity()) : "") + "\n";
System.out.println(req + "\n" + res );
return Arrays.asList(req, res);
}
}
}
List sendGet(String url, Map<String,String> body) {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(2000)
.setSocketTimeout(3000)
.build();
RequestBuilder requestBuilder = RequestBuilder.get()
.setConfig(requestConfig)
.setUri(url)
.setHeader(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8");
body.forEach({key, value -> requestBuilder.addParameter(key, value)});
HttpUriRequest request = requestBuilder.build();
String req = "REQUEST:" + "\n" + request.getRequestLine() + "\n" + "Headers: " +
request.getAllHeaders() + "\n";
HttpClientBuilder.create().build().withCloseable {httpClient ->
httpClient.execute(request).withCloseable {response ->
String res = "RESPONSE:" + "\n" + response.getStatusLine() + "\n" + "Headers: " +
response.getAllHeaders() + "\n" +
(response.getEntity() != null ? EntityUtils.toString(response.getEntity()) : "") + "\n";
System.out.println(req + "\n" + res );
return Arrays.asList(req, res);
}
}
}
The approach which is normally used in JMeter is placing your request under the While Controller which will be checking the Status value which in its turn can be fetched from the response using a suitable Post-Processor so the request will be retried unless the "Status" changes to some value which you expect (or times out)
If you place the whole construction under the Transaction Controller you will get the whole time for the status to change.
Example test plan outline:

Null Response on HttpWebRequest.GetResponse()?

I'm using http://dictionary.reference.com/browse/:word and check the status of returned response to evaluate whether the 'word' definition exists or not. It works fine for correct words (200 status code). But for those spelled incorrectly (404 status code), I'm unable to catch the status code from HttpWebRequest.GetResponse(), as it returns null?
The thing is I'm using PostMan to check and I did receive status code 404 there for the following url:
http://dictionary.reference.com/browse/sdfsdsdc
Here's my implementation:
string baseURL = "http://dictionary.reference.com/browse";
bool result = false;
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(baseURL + "/" + word);
request.Method = "GET";
//request.Timeout = 2000;
request.KeepAlive = false;
request.ContentType = "text/html; charset=UTF-8";
Console.WriteLine(request.RequestUri);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
HttpStatusCode statusCode = response.StatusCode;
int statusCodeNumber = (int)statusCode;
Console.WriteLine("Status Code: " + statusCode + " - status number: " + statusCodeNumber);
try
{
if (statusCodeNumber == 200) result = true;
else if (statusCodeNumber == 404) { result = false; }
else { throw new UnknownStatusCodeException(); }
}
catch (UnknownStatusCodeException e) {}
response.Close();
}
catch (WebException e) {
}
}
Here's the WebException I caught
full-size-pic
Could someone give me some pointers? Thanks

CKEditor file upload doesn't work properly with mvc 6

I'm trying to use the built in upload file of CKEditor, it works with my MVC5 project, but it doesn't work with my MVC6 project, the code for uploading the file is correct, I've tested it, and it actually upload the file to the server, but it doesn't populate the form with the URL and image information, here's the code for my MVC5 project that works:
public ActionResult UploadImage(HttpPostedFileBase upload, string CKEditorFuncNum, string CKEditor,
string langCode)
{
string vImagePath = String.Empty;
string vMessage = String.Empty;
string vFilePath = String.Empty;
string vOutput = String.Empty;
try
{
if (upload != null && upload.ContentLength > 0)
{
var vFileName = DateTime.Now.ToString("yyyyMMdd-HHMMssff") + " - " + Path.GetFileName(upload.FileName);
var vFolderPath = Server.MapPath("/Upload/");
if (!Directory.Exists(vFolderPath))
{
Directory.CreateDirectory(vFolderPath);
}
vFilePath = Path.Combine(vFolderPath, vFileName);
upload.SaveAs(vFilePath);
vImagePath = Url.Content("/Upload/" + vFileName);
vMessage = "The file uploaded successfully.";
}
}
catch(Exception e)
{
vMessage = "There was an issue uploading:" + e.Message;
}
vOutput = #"<html><body><script>window.parent.CKEDITOR.tools.callFunction(" + CKEditorFuncNum + ", \"" + vImagePath + "\", \"" + vMessage + "\");</script></body></html>";
return Content(vOutput);
}
And here is the code for MVC6 project that doesn't work:
public async Task<ActionResult> UploadImage(IFormFile upload, string CKEditorFuncNum, string CKEditor,
string langCode)
{
string vImagePath = String.Empty;
string vMessage = String.Empty;
string vFilePath = String.Empty;
string vOutput = String.Empty;
try
{
if (upload != null && upload.Length > 0)
{
var vFileName = DateTime.Now.ToString("yyyyMMdd-HHMMssff") + " - " + ContentDispositionHeaderValue.Parse(upload.ContentDisposition).FileName.Trim('"');
var vFolderPath = Path.Combine(_environment.WebRootPath, "Files", "ArticleUploads");
if (!Directory.Exists(vFolderPath))
{
Directory.CreateDirectory(vFolderPath);
}
vFilePath = Path.Combine(vFolderPath, vFileName);
await upload.SaveAsAsync(vFilePath);
vImagePath = Url.Content("/Files/ArticleUploads/" + vFileName);
vMessage = "The file uploaded successfully.";
}
}
catch (Exception e)
{
vMessage = "There was an issue uploading:" + e.Message;
}
vOutput = #"<html><body><script>window.parent.CKEDITOR.tools.callFunction(" + CKEditorFuncNum + ", \"" + vImagePath + "\", \"" + vMessage + "\");</script></body></html>";
return Content(vOutput);
}
And in CKEditor config file I have:
config.filebrowserImageUploadUrl = '/Admin/Article/UploadImage';
I've inspected the variables, and they send the same value, also worth to note that I'm using the same version of CKEditor, so that can't be the problem, I'd appreciate any help on this.
If the file gets uploaded and you don't see the image gets populated, I guess there should be some problem with the way you return your content, since you are returning html, try to specify your content type, like so:
return Content(vOutput, "text/html");
If that didn't solve your problem, you need to provide more information, tell us what exactly you get from this action in JavaScript side.

AD with LDAP connection error

Im trying to use a .net application but the application cant find the server in my local network.
Im using LdapExploreTool 2 with the following settings:
the base DN is "DC=exago,DC=local", the Ip address "192.168.1.250" and the server name "exago.local"
The connection is successful and this is the result:
Inputing the values:
Examining the code, i get the exception when "Bind to the native AdsObject to force authentication":
"The specified domain either does not exist or could not be contacted."
public bool IsAuthenticated(string domain, string ldapPath, string username, string pwd, string userToValidate)
{
string domainAndUsername = domain + #"\" + username;
if (string.IsNullOrEmpty(ldapPath))
SetLdapPath(domain);
else
_path = ldapPath;
App.Services.Log.LogUtils.WriteLog(Log.LogLevel.INFO, "IsAuthenticated_DirectoryEntry:" + _path + "," + domainAndUsername + "," + pwd);
DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, pwd);
//check if domain is valid
int domainId = AppDomains.GetDomainIdByName(domain);
if (domainId == int.MinValue)
{
return false;
}
AppDomains d = AppDomains.GetRecord(domainId);
List<AppDomainQueries> lQueries = new List<AppDomainQueries>(AppDomainQueries.GetArray());
lQueries = lQueries.FindAll(delegate(AppDomainQueries dq) { return dq.DomainId == domainId && dq.Status == 'A'; });
string queryString = string.Empty;
try
{
// Bind to the native AdsObject to force authentication.
Object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
string ldapAndQuerie = string.Empty;
//base account search
queryString = "(SAMAccountName=" + userToValidate + ")";
if (username != userToValidate)
{
if (lQueries.Count == 1)
ldapAndQuerie = lQueries.FirstOrDefault().QueryString;
if ((ldapAndQuerie != string.Empty) && (ldapAndQuerie != "*") && (ldapAndQuerie != "(objectClass = user)"))
queryString = "(&(SAMAccountName=" + userToValidate + ")" + ldapAndQuerie + ")";
}
search.Filter = queryString;
App.Services.Log.LogUtils.WriteLog(Log.LogLevel.INFO, "LDAP=" + queryString);
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
if (null == result)
{
return false;
}
// Update the new path to the user in the directory
_path = result.Path;
_filterAttribute = (String)result.Properties["cn"][0];
}
catch (Exception ex)
{
App.Services.Log.LogUtils.WriteLog(Log.LogLevel.ERROR, "App.Services.Core.LdapAuthentication.IsAuthenticated() Exception - (LDAP=" + queryString + ")" + ex.Message, ex);
return false;
}
return true;
}
How can i establish a connection?
The problem was the LDAP connection string,
it seems that it missed the actual location(IP + port) in the network.
LDAP://192.168.1.250:389/DC=exago,DC=local

Resources