Why is this RestSharp file upload not working? - asp.net-web-api

I have this ASP.NET Core Web API action method:
[HttpPost("PostDir")]
[DisableRequestSizeLimit]
public async Task<IActionResult> PostDir(string serverPath)
{
// Do stuff with file.
return Ok();
}
I don't know what to do with the file I am trying to upload or what it looks like in the action method because the action is never invoked: the client code below gets a 404 response:
public async Task PostDirAsync(string localDirPath, string serverDir)
{
var sourcePath = Path.Combine("Temp", Guid.NewGuid() + ".zip");
ZipFile.CreateFromDirectory(localDirPath, sourcePath, CompressionLevel.Fastest, true);
var rest = new RestClient("http://localhost:50424/api/File/PostDir");
var req = new RestRequest(Method.POST);
req.AddFile(Path.GetFileName(sourcePath), sourcePath);
req.AddHeader("Content-Type", "multipart/form-data");
req.AddParameter("serverPath", serverDir, ParameterType.QueryString);
var resp = rest.Execute(req);
}
What am I missing or doing wrong?

Related

download in async httpclient xml file

I want to download an xml file in asynchronous and let the user know that the file is downloading while it does other moves in the app
public static async Task<string> GetRequestAsync(string url)
{
using (var httpClient = new HttpClient() { MaxResponseContentBufferSize = int.MaxValue })
{
HttpResponseMessage response = await httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
with this command did not work successfully

Getting 400 bad request when I use "ValidateAntiForgeryToken" and "Authorize"

I'm using asp.net core in the server side and xamarin in the client side.I use JWT token and I want to validate forgery token at the same time.
This is my client side code :
public async Task<string> PostAsync(object model, string url)
{
var cookieContainer = new CookieContainer();
var handlerhttps = new HttpClientHandler
{
UseCookies = true,
UseDefaultCredentials = true,
CookieContainer = cookieContainer
};
var clientPage = new HttpClient(handler: handlerhttps)
{
BaseAddress = new Uri(uriString: Application.Current.Resources[index: "Domain"] + "/api/token")
};
var pageWithToken = await clientPage.GetAsync(requestUri: clientPage.BaseAddress);
var verificationToken = await pageWithToken.Content.ReadAsStringAsync();
using (var handler = new HttpClientHandler
{
CookieContainer = cookieContainer,
UseDefaultCredentials = true,
UseCookies = true
})
{
using (var client = new HttpClient(handler: handler) {BaseAddress = new Uri(uriString: url)})
{
client.DefaultRequestHeaders.Add(name: "RequestVerificationToken", value: verificationToken);
if (Application.Current.Properties[key: "Token"] != null)
{
var token = Application.Current.Properties[key: "Token"].ToString();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue(scheme: "Bearer", parameter: token);
}
var json = JsonConvert.SerializeObject(value: model);
var content = new StringContent(content: json, encoding: Encoding.UTF8,
mediaType: "application/json");
var response = await client.PostAsync(requestUri: client.BaseAddress, content: content);
var result = await response.Content.ReadAsStringAsync();
return result;
}
}
}
My problem is when I use [ValidateAntiForgeryToken] and [Authorize] in the server side at the same time, I get 400 bad request.
But when I remove [ValidateAntiForgeryToken], It will authorize without any problem.
When I remove [Authorize] , I don't get 400 bad request and it validate forgery token successfully.
I don't know how to solve this problem.
If you are using Microsoft.AspNetCore.Mvc.TagHelpers it will add a input field with a 'difficult to guess' code:
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8PXv-VNSuRBLvOlUgHlQcf4p8B29vW6EKn4ENesSgHR79kWTvbnQ9a1Taj90b-e66-79H7Nx5ljHnvPbwqfSNqHMRMaBkoRKGsTxtbZZlq0rSl2zbGK2aKpPQc0qnoNuRehSNhP097P5-Vlp-3OSPYdIqLQJSqIsPDaQsEOXsNU4qIIDrj-tIhqk5EW9tTYc6g">
Anyways, even if you add #Html.AntiForgeryToken() it wouldn't conflict. However you cannot decorate the 'first' controller action with [ValidateAntiForgeryToken], only the final one with will get the POST.
Example:
Action 1
[HttpPost]
[AllowAnonymous]
[ActionName("SpecialSignUp")]
public IActionResult Index([FromForm] string email)
{
// TODO : code in here
return View(email);
}
Users will be redirect to above action through a POST.
Let's say that the view above displays a form with the email field pre-filled and other fields to be filled.
If you decorate it with [ValidateAntiForgeryToken] you will get a 400 (Bad Request). Removing it, all will be fine.
Action 2
[HttpPost]
[AllowAnonymous] // It could be [Authorized]
[ActionName("SpecialSignUp")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> LaunchSignUpAsync([FromForm] SpecialSignUpViewModel model)
{
// TODO : Code in here
return RedirectToAction("OtherActionX", data);
}
Form will be posted by the above View
Now all it's working, no conflict is happening anymore. If you respect that sequence, it will work for you!
I had the same issue, and it was happening because I decorated the 'Action 1' with [ValidateAntiForgeryToken] as well.
Hopefully it helps!
I faced a similar issue but got it resolved by adding "RequestVerificationToken" on my request
My controller code (sample)
HttpPost("SignOut")
Authorize ==> using JWT
ValidateAntiForgeryToken
*/
You can try making a custom method for validation of JWT token to replace the
[Authorize] by
public void ValidateJWT(string token, out bool status)
{
if (token == null)
{
status = false;
}
byte[] secretKey = System.Text.Encoding.UTF8.GetBytes("your jwt secret key");
var tokenHandler = new JwtSecurityTokenHandler();
try
{
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(secretKey),
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);
status = true;
}
catch
{
status = false;
}
}

Make IFormFile function to work with model

I have a function in my controller that takes a file sent by an ajax call and saves it to a specified path. I was wondering how I could make this work with a model instead as I am hoping to send more data than just the image.
ViewModel:
public class PhotoViewModel
{
// Other strings
public IFormFile userimage { get; set; }
}
Controller: Without model (working)
[HttpPost]
public async Task<IActionResult> Post(IFormFile file)
{
var filePath = Path.GetFullPath(#"C:\Users\me\documents\" + file.FileName);
if (file.Length > 0)
{
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
}
return StatusCode(200);
}
Attempt at Version with Model:
[HttpPost]
public async Task<IActionResult> PhotoData(PhotoViewModel model)
{
var filePath = Path.GetFullPath(#"C:\Users\me\documents\" + model.userimage.FileName);
if (ModelState.IsValid)
{
if (model.userimage.Length > 0)
{
using (var stream = new FileStream(filePath, FileMode.Create))
{
await model.userimage.CopyToAsync(stream);
}
}
}
return StatusCode(200);
}
This attempt doesn't get me far. By setting a breakpoint I can see it fails at setting the filePath but I'm not sure how to work with the model. Any help is appreciated.
What is the error message you are getting and what is the client side code you are using to send the API request?
You will have to use a FormData object and fill the FormData object with the required properties.
var formData = new FormData();
formData.append(add PhotoViewModel properties)
formData.append(userimage, <file>);

Return an HttpResponse in an APIController Method which calls a different API

I have an APIController Method as below. Basically I need to validate an API response. So it's an API call within an API call.
public class DCController : ApiController
{
[HttpPost]
public HttpResponseMessage SampleMethod(string url)
{
var uri = new Uri(url);
var baseAddress = uri.GetLeftPart(System.UriPartial.Authority);
var apiAddress = url.Replace(baseAddress + "/", "");
var responseString = string.Empty;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = client.GetAsync(apiAddress).Result;
if (response.IsSuccessStatusCode)
{
responseString = response.Content.ReadAsStringAsync().Result;
}
}
if (!string.IsNullOrEmpty(responseString) && responseString.ToString().Validate())
{
return Request.CreateResponse(HttpStatusCode.OK, "Validated");
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Invalid");
}
}
Issue:
1. Request object is null in the return lines.
2. If i try creating a request object -
var request = new HttpRequestMessage();
It throws below error:
An exception of type 'System.InvalidOperationException' occurred in
System.Web.Http.dll but was not handled in user code
Additional information: The request does not have an associated
configuration object or the provided configuration was null.
Not sure what settings I need to add. I am relatively new to working with APIs. Any help is appreciated.
I could get it working by below code -
[HttpPost]
public HttpResponseMessage Get(string url)
{
string responseString = GetWebApiData(url); //Extracted the method
HttpResponseMessage response = new HttpResponseMessage();
if (!string.IsNullOrEmpty(responseString) && responseString.ToString().Validate())
{
response.ReasonPhrase = "Valid";
response.StatusCode = HttpStatusCode.OK;
}
else
{
response.ReasonPhrase = "Invalid";
response.StatusCode = HttpStatusCode.BadRequest;
}
return response;
}

Resharpe.portable get Twitter request token

Hello i'm doing an xamarin.form application and i'm implementing the twitter login using oauth.
I have problem to get the request_token folowing the link:
https://dev.twitter.com/oauth/reference/post/oauth/request_token
using restsharp.portable for the request POST i arrive at this point:
public async void GetTwitterToken()
{
try
{
TwitterLogin tw = new TwitterLogin();
RestClient client = new RestClient("https://api.twitter.com");
RestRequest request = new RestRequest("/oauth/request_token", Method.POST);
client.Authenticator = OAuth1Authenticator.ForRequestToken(tw.oauth_consumer_key, tw.oauth_consumer_secret);
IRestResponse response = await client.Execute(request);
}
catch (Exception e)
{
}
}
Parameter "response" it's ok but i'don't know how to parse to get token (it's not json).
i have seen this example:
public void GetRequestToken()
{
var client = new RestClient("https://api.twitter.com"); // Note NO /1
client.Authenticator = OAuth1Authenticator.ForRequestToken(
_consumerKey,
_consumerSecret,
"http://markashleybell.com" // Value for the oauth_callback parameter
);
var request = new RestRequest("/oauth/request_token", Method.POST);
var response = client.Execute(request);
var qs = HttpUtility.ParseQueryString(response.Content);
_token = qs["oauth_token"];
_tokenSecret = qs["oauth_token_secret"];
}
But i don't have HttpUtility.ParseQueryString(response.Content) whith xamarin.form framework

Resources