I`m do proxy service in asp.net core, extensions where the request will be routed to another service.
My extension:
public static IApplicationBuilder UseProxy(this IApplicationBuilder builder, List<ProxySetting> options)
{
builder.Use(async (context, next) =>
{
var resultPathHandler = options.ProxySettingHandler(context.Request.Path, context.Request.Method);
if (!resultPathHandler.Equal)
//continues through the rest of the pipeline
await next();
else
{
using (var httpClient = new HttpClient())
{
var pathSetting = resultPathHandler.Setting;
var requestMessage = new HttpRequestMessage();
//добавляем хедеры
foreach (var header in context.Request.Headers)
{
if (!httpClient.DefaultRequestHeaders.TryAddWithoutValidation(header.Key, header.Value.ToArray()))
{
httpClient.DefaultRequestHeaders.TryAddWithoutValidation(header.Key,
header.Value.ToArray());
}
}
if (context.Request.HasFormContentType && context.Request.Form.Count > 0)
{
var temp = new Dictionary<string, object>();
foreach (var form in context.Request.Form)
{
requestMessage.Properties.Add(form.Key, form.Value);
temp.Add(form.Key, form.Value);
}
var jsonString = JsonConvert.SerializeObject(temp).Replace(":[", ":").Replace("],",",");
var mediatype = string.Empty;
if (context.Request.ContentType.Contains(';'))
mediatype = context.Request.ContentType.Split(';')[0];
else
mediatype = context.Request.ContentType;
requestMessage.Content = new StringContent(jsonString, Encoding.UTF8, mediatype);
}
requestMessage.Headers.Host = pathSetting.Host;
var host = pathSetting.GetUri(context.Request.Path);
var uriString = $"{host}{context.Request.QueryString}";
requestMessage.RequestUri = new Uri(uriString);
requestMessage.Method = new HttpMethod(pathSetting.Method);
var response = await httpClient.SendAsync(requestMessage);
var result = await response.Content.ReadAsStringAsync();
var resultObj = JsonConvert.DeserializeObject<object>(result);
context.Response.StatusCode = (int)response.StatusCode;
await context.Response.WriteAsync(resultObj.ToString());
}
}
});
return builder;
}
where this code:
if (context.Request.HasFormContentType && context.Request.Form.Count > 0)
{
var temp = new Dictionary<string, object>();
foreach (var form in context.Request.Form)
{
requestMessage.Properties.Add(form.Key, form.Value);
temp.Add(form.Key, form.Value);
}
var jsonString = JsonConvert.SerializeObject(temp).Replace(":[", ":").Replace("],",",");
var mediatype = string.Empty;
if (context.Request.ContentType.Contains(';'))
mediatype = context.Request.ContentType.Split(';')[0];
else
mediatype = context.Request.ContentType;
requestMessage.Content = new StringContent(jsonString, Encoding.UTF8, mediatype);
}
Add to content post and put parameters, with application/x-www-form-urlencoded or application/form-data, and send to other service, but i dont get this parameters in other service.
Help me, need release this feature. Thx and sorry for my bad English
You don't need to to reinvent the wheel. ASP.NET Core already has and provides own ProxyMiddleware.
Related
I am attempting to upgrade to newest APNS connectivity functionality but when I submit a request I get a http 400 bad request result with no reason. What am I missing / doing wrong?
Method for sending below:
public async void SendAsync(string deviceToken, string p8privateKey, string p8privateKeyId, string teamId)
{
var path = $"/3/device/{deviceToken}";
var obj = new
{
aps = new
{
alert = "test00001"
}
};
var json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
var request = new HttpRequestMessage(HttpMethod.Post, new Uri("https://api.development.push.apple.com:443" + path))
{
Version = new Version(2, 0)
};
string jwToken = CreateJwtToken(p8privateKey, p8privateKeyId, teamId);
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", jwToken);
request.Headers.TryAddWithoutValidation(":method", "POST");
request.Headers.TryAddWithoutValidation(":path", path);
request.Headers.Add("apns-topic", "com.the-app");
request.Content = new StringContent(json);
string sReq = JsonConvert.SerializeObject(request);
string jsonContent = request.Content.ReadAsStringAsync().Result;
WinHttpHandler handler = new WinHttpHandler();
HttpClient http = new HttpClient(handler);
var t = await http.SendAsync(request);
}
Here are the other used methods:
private static string CreateJwtToken(string p8privateKeyId, string p8privateKey, string teamId)
{
var header = JsonHelper.Serialize(new { alg = "ES256", kid = p8privateKeyId });
var payload = JsonHelper.Serialize(new { iss = teamId, iat = ToEpoch(DateTime.UtcNow) });
var key = CngKey.Import(Convert.FromBase64String(p8privateKey), CngKeyBlobFormat.Pkcs8PrivateBlob);
using (var dsa = new ECDsaCng(key))
{
dsa.HashAlgorithm = CngAlgorithm.Sha256;
var headerBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(header));
var payloadBasae64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(payload));
var unsignedJwtData = $"{headerBase64}.{payloadBasae64}";
var signature = dsa.SignData(Encoding.UTF8.GetBytes(unsignedJwtData));
return $"{unsignedJwtData}.{Convert.ToBase64String(signature)}";
}
}
private static int ToEpoch(DateTime time)
{
var span = DateTime.UtcNow - new DateTime(1970, 1, 1);
return Convert.ToInt32(span.TotalSeconds);
}
I have limited to the payload to what I think is the bear minimum requirements. I am new to jwt/http2 and APNS.
I could very well be missing something simple.
I am attempting to send POST data to my server and get back a response. For some reason, no POST data is actually getting sent. A request is being sent to my server but the POST array is empty.
Here is my code for sending the request:
public class GlobalMethods
{
public async Task<string> callAjax(string mthd,NameValueCollection parameters)
{
var client = new HttpClient();
var content = JsonConvert.SerializeObject(parameters);
var result = await client.PostAsync("http://dev.adex-intl.com/adex/mvc/receiving/"+mthd, new StringContent(content)).ConfigureAwait(false);
var tokenJson = "";
if (result.IsSuccessStatusCode)
{
tokenJson = await result.Content.ReadAsStringAsync();
}
return tokenJson;
}
}
And here is my code that calls the above method:
public void loginPressed(object sender, EventArgs e)
{
if(String.IsNullOrEmpty(badge.Text)) {
DisplayAlert("Error", "Enter your badge number", "Ok");
} else {
IsBusy = true;
NameValueCollection parameters = new NameValueCollection();
parameters["badgetNumber"] = badge.Text;
GlobalMethods globalMethods = new GlobalMethods();
var results = globalMethods.callAjax("login", parameters);
}
}
I'm not sure what I'm doing wrong. Also, I'm a newbie to Xamarin and C# so I'm not even sure if the way I am attempting to do things is the best way.
You haven't specify the type of content that you want to send, in your case it's 'application/json', you can set it like that:
"var client = new HttpClient();
var content = new StringContent(JsonConvert.SerializeObject(parameters));
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");". Also, I would suggest you to write code like that:
var uri = new Uri(url);
using (var body = new StringContent(JsonConvert.SerializeObject(data)))
{
body.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var request = new HttpRequestMessage
{
Version = new Version(1, 0),
Content = body,
Method = HttpMethod.Post,
RequestUri = uri
};
try
{
using (var response = await _client.SendAsync(request,cancellationToken))
{
if (response.IsSuccessStatusCode)
{
//Deal with success response
}
else
{
//Deal with non-success response
}
}
}
catch(Exception ex)
{
//Deal with exception.
}
}
You can use PostAsync for async sending data to server. your code should be something like this:
HttpClient client = new HttpClient();
var values = new Dictionary<string, string>
{
{ "p1", "data1" },
{ "p2", "data2" }
};
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("http://www.example.com/index.php", content);
var responseString = await response.Content.ReadAsStringAsync();
I have an object.
I'am sending it this to my api project this way :
mymodel obj = new mymodel();
obj.prop = "this";
obj.prop2 = "prop2";
var content = JsonConvert.SerializeObject(obj);
var buffer = System.Text.Encoding.UTF8.GetBytes(content);
var byteContent = new ByteArrayContent(buffer);
byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
string response = "";
using (HttpClient client = new HttpClient())
{
var rez = await client.PostAsync(uri + myenum.Insert, byteContent).ConfigureAwait(false);
response = rez.ToString();
}
In my api method i want to convert that string or http content again to model.
[ActionName("Insert")]
[HttpGet]
public bool Insert(string obj)
{
try
{
mymodel model = JsonConvert.DeserializeObject<mymodel>(obj);
How to handle object i'am sending with postasync in my api method ?
Any help ?
First you cannot use PostAsync on a HTTPGet method.
Second, I dont understand what you mean. If you are using json then you dont have to do anything. Just have a simple client method as such:
public async Task<TResult> PostAsync<TResult, TInput>(string uriString, TInput payload = null) where TInput : class
{
var uri = new Uri(uriString);
using (var client = GetHttpClient())
{
var jsonContent = JsonConvert.SerializeObject(payload, Formatting.Indented, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() });
HttpResponseMessage response = await client.PostAsync(uri, new StringContent(jsonContent, Encoding.UTF8, "application/json"));
if (response.StatusCode != HttpStatusCode.OK)
{
//Log.Error(response.ReasonPhrase);
return default(TResult);
}
var json = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<TResult>(json);
}
}
And you can just add the same object to your API like
[ActionName("Insert")]
[HttpPost]
public bool Insert(YourObjectClass obj)
{
try
{
....code....
}
}
I have no idea how to POST JSON with HttpClient. I find some solution, like this, but I have to use HttpClient, cause of async and have to add a header.
This is my code below. Any idea how to fix it?
List<Order> list = new List<Order> { new Order() { Name = "CreatedTime", OrderBy = 1 } };
Queues items = new Queues { Orders = list };
var values = new Dictionary<string, string> { { "Orders", JsonConvert.SerializeObject(list) } };
var content = new FormUrlEncodedContent(values);
//HttpContent cc = new StringContent(JsonConvert.SerializeObject(items));
_msg = await _client.PostAsync(input, content);
//_msg = await _client.PostAsync(input, cc);
var response = await _msg.Content.ReadAsStringAsync();
You can use the method PostAsJsonAsync which can be found in the extensions assemblies:
System.Net.Http.Formatting.dll
Example
public static async Task SendJsonDemo(object content)
{
using(var client = new HttpClient())
{
var response = await client.PostAsJsonAsync("https://example.com", content);
}
}
If you want to add custom headers to the request, add it to DefaultRequestHeaders:
client.DefaultRequestHeaders.Add("mycustom", "header1");
You can send any type of request like as
public static async Task<HttpResponseMessage> SendRequest(HttpMethod method, string endPoint, string accessToken, dynamic content = null)
{
HttpResponseMessage response = null;
using (var client = new HttpClient())
{
using (var request = new HttpRequestMessage(method, endPoint))
{
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
if (content != null)
{
string c;
if (content is string)
c = content;
else
c = JsonConvert.SerializeObject(content);
request.Content = new StringContent(c, Encoding.UTF8, "application/json");
}
response = await client.SendAsync(request).ConfigureAwait(false);
}
}
return response;
}
I'm trying to upload an audio track to the Soundcloud.com using C#.NET, but there aren't any resources for .NET anywhere. Could someone post a link or an example of how to upload an audio file to my Soundcloud.com account using .NET?
Thank you,
Arman
To upload an audio using soundcloud's REST API you need to take care of HTTP POST related issues (RFC 1867). In general, ASP.NET does not support sending of multiple files/values using POST, so I suggest you to use Krystalware library: http://aspnetupload.com/Upload-File-POST-HttpWebRequest-WebClient-RFC-1867.aspx
After that you need to send proper form fields to the https://api.soundcloud.com/tracks url:
Auth token (oauth_token)
Track Title (track[title])
The file (track[asset_data])
Sample code:
using Krystalware.UploadHelper;
...
System.Net.ServicePointManager.Expect100Continue = false;
var request = WebRequest.Create("https://api.soundcloud.com/tracks") as HttpWebRequest;
//some default headers
request.Accept = "*/*";
request.Headers.Add("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.3");
request.Headers.Add("Accept-Encoding", "gzip,deflate,sdch");
request.Headers.Add("Accept-Language", "en-US,en;q=0.8,ru;q=0.6");
//file array
var files = new UploadFile[] {
new UploadFile(Server.MapPath("Downloads//0.mp3"), "track[asset_data]", "application/octet-stream")
};
//other form data
var form = new NameValueCollection();
form.Add("track[title]", "Some title");
form.Add("track[sharing]", "private");
form.Add("oauth_token", this.Token);
form.Add("format", "json");
form.Add("Filename", "0.mp3");
form.Add("Upload", "Submit Query");
try
{
using (var response = HttpUploadHelper.Upload(request, files, form))
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
lblInfo.Text = reader.ReadToEnd();
}
}
}
catch (Exception ex)
{
lblInfo.Text = ex.ToString();
}
The example code allows you to upload an audio file from the server (notice the Server.MapPath method to form path to the file) and to get a response in json format (reader.ReadToEnd)
Here is a code snippet to upload track via the SoundCloud API =>
using (HttpClient httpClient = new HttpClient()) {
httpClient.DefaultRequestHeaders.ConnectionClose = true;
httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("MySoundCloudClient", "1.0"));
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("OAuth", "MY_AUTH_TOKEN");
ByteArrayContent titleContent = new ByteArrayContent(Encoding.UTF8.GetBytes("my title"));
ByteArrayContent sharingContent = new ByteArrayContent(Encoding.UTF8.GetBytes("private"));
ByteArrayContent byteArrayContent = new ByteArrayContent(File.ReadAllBytes("MYFILENAME"));
byteArrayContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
MultipartFormDataContent content = new MultipartFormDataContent();
content.Add(titleContent, "track[title]");
content.Add(sharingContent, "track[sharing]");
content.Add(byteArrayContent, "track[asset_data]", "MYFILENAME");
HttpResponseMessage message = await httpClient.PostAsync(new Uri("https://api.soundcloud.com/tracks"), content);
if (message.IsSuccessStatusCode) {
...
}
Here another way to get non expiring token and upload track to SoundCloud using C#:
public class SoundCloudService : ISoundPlatformService
{
public SoundCloudService()
{
Errors=new List<string>();
}
private const string baseAddress = "https://api.soundcloud.com/";
public IList<string> Errors { get; set; }
public async Task<string> GetNonExpiringTokenAsync()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseAddress);
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("client_id","xxxxxx"),
new KeyValuePair<string, string>("client_secret","xxxxxx"),
new KeyValuePair<string, string>("grant_type","password"),
new KeyValuePair<string, string>("username","xx#xx.com"),
new KeyValuePair<string, string>("password","xxxxx"),
new KeyValuePair<string, string>("scope","non-expiring")
});
var response = await client.PostAsync("oauth2/token", content);
if (response.StatusCode == HttpStatusCode.OK)
{
dynamic data = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
return data.access_token;
}
Errors.Add(string.Format("{0} {1}", response.StatusCode, response.ReasonPhrase));
return null;
}
}
public async Task UploadTrackAsync(string filePath)
{
using (var client = new HttpClient())
{
client.BaseAddress=new Uri(baseAddress);
var form = new MultipartFormDataContent(Guid.NewGuid().ToString());
var contentTitle = new StringContent("Test");
contentTitle.Headers.ContentType = null;
form.Add(contentTitle, "track[title]");
var contentSharing = new StringContent("private");
contentSharing.Headers.ContentType = null;
form.Add(contentSharing, "track[sharing]");
var contentToken = new StringContent("xxxxx");
contentToken.Headers.ContentType = null;
form.Add(contentToken, "[oauth_token]");
var contentFormat = new StringContent("json");
contentFormat.Headers.ContentType = null;
form.Add(contentFormat, "[format]");
var contentFilename = new StringContent("test.mp3");
contentFilename.Headers.ContentType = null;
form.Add(contentFilename, "[Filename]");
var contentUpload = new StringContent("Submit Query");
contentUpload.Headers.ContentType = null;
form.Add(contentUpload, "[Upload]");
var contentTags = new StringContent("Test");
contentTags.Headers.ContentType = null;
form.Add(contentTags, "track[tag_list]");
var bytes = File.ReadAllBytes(filePath);
var contentFile = new ByteArrayContent(bytes, 0, bytes.Count());
contentFile.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
form.Add(contentFile, "track[asset_data]", "test.mp3");
var response = await client.PostAsync("tracks", form);
}
}
}