Asp.net core disable change string in Uri - .net-core

I have a Encoded string like this:
https://xx.yyy.ir/xx/ff/addUser?name=%d8%b3%d9%84%d8%a7%d9%85
But when I use Uri to convert it to a URL and send it
result = "https://xx.yyy.ir/xx/ff/addUser?name=%d8%b3%d9%84%d8%a7%d9%85"
var client = new HttpClient
{
BaseAddress = new Uri(result.ToString()),
};
var response = await client.GetAsync("");
it send this request :
https://xx.yyy.ir/xx/ff/addUser?name=سلام
why this happen? how to prevent from this?

This is what's causing your problem: new Uri(result.ToString())
Let's try to do this in a proper manner and see what happens.
var builder = new UriBuilder("https://xx.yyy.ir/xx/ff/addUser") { Port = -1 };
var query = HttpUtility.ParseQueryString(builder.Query);
query["name"] = "سلام";
builder.Query = query.ToString();
using var httpClient = new HttpClient();
var response = await client.GetAsync(builder.ToString());
builder.ToString() returns https://xx.yyy.ir/xx/ff/addUser?name=%d8%b3%d9%84%d8%a7%d9%85
So basically, the above code boils down to this:
using var httpClient = new HttpClient();
var response = await client.GetAsync("https://xx.yyy.ir/xx/ff/addUser?name=%d8%b3%d9%84%d8%a7%d9%85");
Tested and verified on my computer.

Related

How can I make proper request for the Identity Server Token Endpoint?

I tried to send an api call to the identity server via .net 6 console application.
Here is the request:
public static async Task<WorkflowResponse> PostRequestToIdentityAsync()
{
var url = "http://didentity/connect/token";
IdentityRequestDataVM identityRequestDataVM = new IdentityRequestDataVM();
identityRequestDataVM.username = "csm";
identityRequestDataVM.password = "MjAyMjox";
identityRequestDataVM.grant_type = "password";
identityRequestDataVM.scope = "m_gln m_msd";
string jsonString = JsonConvert.SerializeObject(identityRequestDataVM);
using (var httpClient = new HttpClient())
{
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(url),
Content = new StringContent(jsonString),
Headers =
{
{"X-Login","override"}
}
};
var user = "gclt";
var password = "glsrt";
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes($"{user}:{password}")));
HttpResponseMessage message = await httpClient.SendAsync(request);
if (message.StatusCode == System.Net.HttpStatusCode.OK)
{
var contents = await message.Content.ReadAsStringAsync();
WorkflowResponse workflowResponse = JsonConvert.DeserializeObject<WorkflowResponse>(contents);
return workflowResponse;
}
else
{
throw new Exception(await message.Content.ReadAsStringAsync());
}
}
}
But, it returned 400 err code (Bad request), is there any mistake in the code snippet ?
It is working fine with postman.

File Uploading using HttpClient in .Net core 3.0 Console Application

I am trying to upload file using HttpClient in Asp.net Core 3, but It is not uploading file to the server. If I try to upload file to the server via Postman, it works.
Below is my simple code to upload file:
HttpClient _client = new HttpClient();
var stream = new FileStream("main.txt", FileMode.Open);
byte[] fileBytes = new byte[stream.Length];
stream.Write(fileBytes, 0, (int)stream.Length);
stream.Dispose();
using (var content = new MultipartFormDataContent())
{
var fileContent = new ByteArrayContent(fileBytes);
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "Test",
};
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
content.Add(fileContent);
_client.PostAsync("http://192.168.56.1:8000", content);
}
As I said above it is working with Postman. I am putting a screenshot which shows that how I doing with Postman.
when I debug the code, so I get below error.
One solution is that you could use MemoryStream to transform the content of the file. Your method will cause the content in the main.txt file to become empty.
Change your code like this:
HttpClient _client = new HttpClient();
Stream stream = new FileStream("main.txt", FileMode.Open);​
MemoryStream ms = new MemoryStream();​
stream.CopyTo(ms);​
byte[] fileBytes = ms.ToArray();​
ms.Dispose(); ​
Another way is that use System.IO.File.ReadAllBytes(filePath).
Try to post file using below example code instead, refer to my answer.
using (var client = new HttpClient())
{
using (var content = new MultipartFormDataContent())
{
//replace with your own file path, below use an txt in wwwroot for example
string filePath = Path.Combine(_hostingEnvironment.WebRootPath, "main.txt");
byte[] file = System.IO.File.ReadAllBytes(filePath);
var byteArrayContent = new ByteArrayContent(file);
content.Add(byteArrayContent, "file", "main.txt");
var url = "https://localhost:5001/foo/bar";
var result = await client.PostAsync(url, content);
}
}
foo/bar action
[HttpPost]
[Route("foo/bar")]
public IActionResult ProcessData([FromForm]IFormFile file)
{
//your logic to upload file
}
I've downloaded the server and tested it with this code. The server returns 200 OK
using (var client = new HttpClient())
{
using (var content = new MultipartFormDataContent())
{
using (var fileStream = new FileStream("test.txt", FileMode.Open))
{
var fileContent = new StreamContent(fileStream);
content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/x-www-form-urlencoded");
content.Add(fileContent, "file", "test.txt");
var response = await client.PostAsync("http://192.168.56.1:8000/", content);
}
}
}

Xamarin form : Token authentication with xamarin form web api

I am working with token based authentication for xamarin form here is my code
public async Task<string> checkLogin(string username, string password)
{
var keyValues = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("username",username),
new KeyValuePair<string, string>("password",password),
new KeyValuePair<string, string>("grant_type","password")
};
var request = new HttpRequestMessage(HttpMethod.Post, "http://softsol.com.pk/Token");
request.Content = new FormUrlEncodedContent(keyValues);
var client = new HttpClient();
var response = await client.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
JObject jdynamic = JsonConvert.DeserializeObject<dynamic>(content);
var accessToken = jdynamic.Value<string>("access_token");
var refershToken = jdynamic.Value<string>("refresh_token");
var date = DateTime.Now.ToString();
var accessTokenExpiration= jdynamic.Value< DateTime> (".expires");
//await Application.Current.MainPage.DisplayAlert("Alert", content, "OK");
Debug.WriteLine(content);
Settings.AccessToken=accessToken;
Settings.RefreshToken = refershToken;
Settings.AccessTokenexpiration = accessTokenExpiration;
return accessToken;
//return response.IsSuccessStatusCode;
}
when I login with usernamre and password I get this error
Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0
and if I run in postman its working fine for example if I run this http://softsol.com.pk/Token in postman with username="test",password="test", grant-type="password" I get the token and its working but I get error from xamarin form. And I am stuck here
I visited the API part of your backend at http://softsol.com.pk/Help and I discovered that http://softsol.com.pk/Token is not there.
Moreover, testing on Postman returns a JSON response :
{
"error": "unsupported_grant_type"
}
With postman, I sent requests both in JSON:
{"username":"test","password":"test","grant-type":"password"}
and as a x-www-form-urlencoded :
I suggest you have to debug properly and analyze the Exemption information.
public async void GetInfoLogin()
{
IEnumerable<KeyValuePair<string, string>> member = new List<KeyValuePair<string, string>>()
{
new KeyValuePair<string, string>("username", UserName.Text),
new KeyValuePair<string, string>("password", PassWord.Text),
new KeyValuePair<string, string>("action", "get_user")
};
HttpContent content = new FormUrlEncodedContent(member);
HttpClient client = new HttpCLient();
var response = await client.PostAsync("(endpoint to server)",content);
var result = await response.Content.ReadAsStringAsync();
var TReturn = (JObject)JsonConvert.DeserializeObject(result);
var success = TReturn.Value<string>("success");
var error = TReturn.Value<string>("error");
var user_id = TReturn.Value<string>("user_id");
var full_name = TReturn.Value<string>("full_name");
var time = TReturn.Value<int>("time");
var send = TReturn.Value<string>("send");
}

Response on created context keeps giving me NullStream

I'm trying to write a middleware for batch requests i .net core 2.0.
So far the I have splitted the request, pipe each request on to the controllers.
The controllers return value, but for some reason the response on the created context that I parse to the controllers keeps giving me a NullStream in the body, so I think that there is something that I miss in my setup.
The code looks like this:
var json = await streamHelper.StreamToJson(context.Request.Body);
var requests = JsonConvert.DeserializeObject<IEnumerable<RequestModel>>(json);
var responseBody = new List<ResponseModel>();
foreach (var request in requests)
{
var newRequest = new HttpRequestFeature
{
Body = request.Body != null ? new MemoryStream(Encoding.ASCII.GetBytes(request.Body)) : null,
Headers = context.Request.Headers,
Method = request.Method,
Path = request.RelativeUrl,
PathBase = string.Empty,
Protocol = context.Request.Protocol,
Scheme = context.Request.Scheme,
QueryString = context.Request.QueryString.Value
};
var newRespone = new HttpResponseFeature();
var requestLifetimeFeature = new HttpRequestLifetimeFeature();
var features = CreateDefaultFeatures(context.Features);
features.Set<IHttpRequestFeature>(newRequest);
features.Set<IHttpResponseFeature>(newRespone);
features.Set<IHttpRequestLifetimeFeature>(requestLifetimeFeature);
var innerContext = _factory.Create(features);
await _next(innerContext);
var responseJson = await streamHelper.StreamToJson(innerContext.Response.Body);
I'm not sure what it is I'm missing in the setup, since innerContext.Response.Body isn't set.
One of the endpoints that I use for testing and that gets hit looks like this
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
I found the error, or two errors for it to work.
First I had to change my newResponse to
var newRespone = new HttpResponseFeature{ Body = new MemoryStream() };
Since HttpResponseFeature sets Body to Stream.Null in the constructor.
When that was done, then Body kept giving an empty string when trying to read it. That was fixed by setting the Position to Zero like
innerContext.Response.Body.Position = 0;

Xamarin Forms HttpClient Multipart/FormData returns 403 Forbidden

I'm trying to make chat app with XamarinForms and I'm trying to upload a file with parameters to server. But I'm getting always 403 Forbidden message. (There is no authentication, there is only token key for now).
If I try to get or send any data to server, it works as well. When I try to send a file with data it returns 403 Forbidden message. I also tried to send same data with Postman. it's worked as well. I'm writing part of code, Could you please tell me, I made it wrong where?
Thanks in advance.
private async Task<HttpClient> GetClient()
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("X-Token-Key", ServiceToken);
client.DefaultRequestHeaders.UserAgent.Add(new System.Net.Http.Headers.ProductInfoHeaderValue("Chrome", "41.0.2228.0"));
return client;
}
If I send text message, it works as well.
public async Task<MobileResult> SendConversationTextMessage(MessageModel message)
{
HttpClient client = await GetClient();
string param = JsonConvert.SerializeObject(message);
var response = await client.PostAsync(Url + "conversation/message_add_text", new StringContent(param, Encoding.UTF8, "application/json"));
var mobileResult = JsonConvert.DeserializeObject<MobileResult>(await response.Content.ReadAsStringAsync());
return mobileResult;
}
If I send message with data, it returns 403 Forbidden
public async Task<MobileResult> SendConversationFileMessage(
FileModel FileMessage,
int UserRemoteId,
int ConversationId,
int ToUserId,
string SendedTime,
MessageModel.MessageType Type,
MessageModel.MessageStatus Status,
string MessageType)
{
HttpClient client = await GetClient();
string PostUrl = Url + "conversation/message_add_" + MessageType;
MultipartFormDataContent content = new MultipartFormDataContent();
ByteArrayContent baContent = new ByteArrayContent(FileMessage.BinaryData);
StringContent UserIdContent = new StringContent(UserRemoteId.ToString());
StringContent ConversationIdContent = new StringContent(ConversationId.ToString());
StringContent ToUserIdContent = new StringContent(ToUserId.ToString());
StringContent SendedTimeContent = new StringContent(SendedTime.ToString());
StringContent TypeContent = new StringContent(Type.ToString());
StringContent StatusContent = new StringContent(Status.ToString());
content.Add(baContent, "AttachedFile", FileMessage.Name);
content.Add(UserIdContent, "serId");
content.Add(ConversationIdContent, "ConversationId");
content.Add(ToUserIdContent, "ToUserId");
content.Add(SendedTimeContent, "SendedTime");
content.Add(TypeContent, "Type");
content.Add(StatusContent, "Status");
try
{
var response = await client.PostAsync(PostUrl, content);
string result = await response.Content.ReadAsStringAsync();
var mobileResult = JsonConvert.DeserializeObject<MobileResult>(result);
return mobileResult;
}
catch (Exception e)
{
return new MobileResult
{
Result = false,
Data = null,
Message = e.ToString()
};
}
}
Postman-Screenshot
Edit: I've tested to send multipart/form-data different way but result is same I'm writing below code:
MultipartFormDataContent content = new MultipartFormDataContent();
var UserIdContent = new StringContent(UserId.ToString());
UserIdContent.Headers.Add("Content-Disposition", "form-data; name=\"UserId\"");
UserIdContent.Headers.Remove("Content-Type");
content.Add(UserIdContent, "UserId");
var ConversationIdContent = new StringContent(ConversationId.ToString());
ConversationIdContent.Headers.Add("Content-Disposition", "form-data; name=\"ConversationId\"");
ConversationIdContent.Headers.Remove("Content-Type");
content.Add(ConversationIdContent, "ConversationId");
var ToUserIdContent = new StringContent(ToUserId.ToString());
ToUserIdContent.Headers.Add("Content-Disposition", "form-data; name=\"ToUserId\"");
ToUserIdContent.Headers.Remove("Content-Type");
content.Add(ToUserIdContent, "ToUserId");
var SendedTimeContent = new StringContent(SendedTime.ToString());
SendedTimeContent.Headers.Add("Content-Disposition", "form-data; name=\"SendedTime\"");
SendedTimeContent.Headers.Remove("Content-Type");
content.Add(SendedTimeContent, "SendedTime");
var TypeContent = new StringContent(Type.ToString());
TypeContent.Headers.Add("Content-Disposition", "form-data; name=\"Type\"");
TypeContent.Headers.Remove("Content-Type");
content.Add(TypeContent, "Type");
var StatusContent = new StringContent(Status.ToString());
StatusContent.Headers.Add("Content-Disposition", "form-data; name=\"Status\"");
StatusContent.Headers.Remove("Content-Type");
content.Add(StatusContent, "Status");
var streamContent = new StreamContent(file.InputStream);
streamContent.Headers.Add("Content-Disposition", "form-data; name=\"AttachedFile\"; filename=\"" + file.FileName + "\"");
streamContent.Headers.Add("Content-Type", "video/mp4");
content.Add(streamContent, "AttachedFile", file.FileName);

Resources