Xamarin Forms HttpClient Multipart/FormData returns 403 Forbidden - xamarin.forms

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);

Related

StatusCode error 500 when sending a POST resquest in XF

I'm writing an API in EF to send FCM notifications:
[HttpPost]
public void PushNotificationToFCM(string deviceTokens, string title, string body, object data, string linkdirection)
{
...
// This registration token comes from the client FCM SDKs.
var registrationToken = deviceTokens;
// See documentation on defining a message payload.
var message = new Message()
{
Apns = new ApnsConfig { Aps = new Aps { ContentAvailable = true, Sound = "default" } },
Data = new Dictionary<string, string>()
{
{ "link", linkdirection },
},
Token = registrationToken,
Notification= new FirebaseAdmin.Messaging.Notification()
{
Title = title,
Body = body,
}
};
// Send a message to the device corresponding to the provided
// registration token.
string response = FirebaseMessaging.DefaultInstance.SendAsync(message).Result;
// Response is a message ID string.
Debug.WriteLine("Successfully sent message: " + response);
}
I tried on Postman or Swagger everything works fine.
I proceed to write the send command in XF:
.xaml.cs
protected async void SendFirebase()
{
string devicetoken = listDeviceID.deviceidphone;
string titlefirebase = "Title";
string bodyfirebase = "Description";
string linkfirebase = "https://applink/..";
await _apiService.AddNotifyFirebase(devicetoken, titlefirebase, bodyfirebase, linkfirebase);
}
public async Task AddNotifyFirebase(string devicetoken, string titlefirebase, string bodyfirebase, string linkfirebase)
{
var model = new
{
devicetoken = devicetoken,
titlefirebase = titlefirebase,
bodyfirebase = bodyfirebase,
linkfirebase = linkfirebase,
};
var json = JsonConvert.SerializeObject(model);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var request = new HttpRequestMessage(HttpMethod.Post, "https://linkapi/api/SendNotifyDeviceFirebase");
request.Content = content;
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
var responseBody = await response.Content.ReadAsStringAsync();
}
}
However I get the error: StatusCode: 500, ReasonPhrase: 'Internal Server Error', Version: 1.1, Content: System.Net.Http.NSUrlSessionHandler+NSUrlSessionDataTaskStreamContent, ....
Where did I go wrong? Looking forward to everyone's help. Thank you!
Update
I check on Swagger:
Everything seems fine!
I then changed the send command back:
public async Task AddNotifyFirebase(string devicetoken, string titlefirebase, string bodyfirebase, string linkfirebase)
{
var request = new HttpRequestMessage(HttpMethod.Post, "https://xxxxxx/api/SendNotifyDeviceFirebase?deviceTokens=" + devicetoken + "&title=" + titlefirebase + "&body=" + bodyfirebase + "&linkdirection=" + linkfirebase);
//request.Headers.Add("Accept-Encoding", "gzip");
//request.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain; charset=utf-8");
HttpResponseMessage response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
var responseBody = await response.Content.ReadAsStringAsync();
}
}
I get the error again: StatusCode: 415, ReasonPhrase: 'Unsupported Media Type'
I have handled the problem. Thank you all
public async Task AddNotifyFirebase(NotifyFireBase NotifyFireBaseAdd)
{
var urlput = "......";
HttpClient client = new HttpClient();
var content = NotifyFireBaseAdd;
var stringContent = new StringContent(JsonConvert.SerializeObject(content), Encoding.UTF8, "application/json");
await client.PostAsync(urlput, stringContent);
}

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.

Notification hub device registration with installation

After reading this I've been trying to create an installation in my xamarin.android app but I keep getting an 'Unauthorized error' I feel that I'm missing something. Any help is appreciated.
Previously I was able to register with the hub using
var regID = hub.Register(token, tags.ToArray()).RegistrationId;
so I'm sure my hub has been setup correctly and that I am using the correct connectionstring.
My installation object
install.installationId = installationId; //guid
install.tags = Tags;
install.platform = "gcm";
install.pushChannel = token; //refresh token from fcm
Call to Create installation
private async Task<HttpStatusCode> CreateOrUpdateInstallationAsync(DeviceInstallation deviceInstallation,
string hubName, string listenConnectionString)
{
if (deviceInstallation.installationId == null)
return HttpStatusCode.BadRequest;
// Parse connection string (https://msdn.microsoft.com/library/azure/dn495627.aspx)
ConnectionStringUtility connectionSaSUtil = new ConnectionStringUtility(listenConnectionString);
string hubResource = "installations/" + deviceInstallation.installationId + "?";
string apiVersion = "api-version=2015-04";
// Determine the targetUri that we will sign
string uri = connectionSaSUtil.Endpoint + hubName + "/" + hubResource + apiVersion;
//=== Generate SaS Security Token for Authorization header ===
// See, https://msdn.microsoft.com/library/azure/dn495627.aspx
string SasToken = connectionSaSUtil.getSaSToken(uri, 60);
using (var httpClient = new HttpClient())
{
string json = JsonConvert.SerializeObject(deviceInstallation);
httpClient.DefaultRequestHeaders.Add("Authorization", SasToken);
var response = await httpClient.PutAsync(uri, new StringContent(json, System.Text.Encoding.UTF8, "application/json"));
return response.StatusCode;
}
}

How to send file with HttpClient post in xamarin forms

I want to send file through post request using httpclient
this what i tried but file didn't sent , when i tried in postman it works fine
string Url = $"http://ataprojects.net/test/products.php?request_type=add&company_name={BaseService.Company}&name={product.name}&barcode={product.barcode}&buy_price={product.buy_price}&sell_price={product.sell_price}";
try
{
using (HttpClient client = new HttpClient())
{
var content = new MultipartFormDataContent();
content.Headers.ContentType.MediaType = "multipart/form-data";
content.Add(new StreamContent(product._mediaFile.GetStream()),
"image",
product.image);
var response = client.PostAsync(Url, content).Result;
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
var contentdata = await response.Content.ReadAsStringAsync();
var Items = JsonConvert.DeserializeObject<AddProductReturnModel>(contentdata);
return Items;
}
else
{
return null;
}
}
}
what's the problem ?
Try This Code
var content = new MultipartFormDataContent();
content.Add(new StreamContent(product._mediaFile.GetStream()),
"\"file\"",
$"\"{product._mediaFile.Path}\"");

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");
}

Resources