PostAsJsonAsync adding leading character to request body - c#

I have strange problem when trying to use PostAsJsonAsync.
In body I get this json with strange leading and trailing characters:
99 {
"SessionReferenceId":"f39dc178-279e-4e3a-bda9-a16829eb0e45",
"GameReferenceId":"netent_es_starburst",
"CurrencyCode":"EUR",
"LossLimit":100,
"ClientType":1
}
0
and on API side this can't be binded and I get Error message that the request cannot have empty body.
Code on the sending side is like this:
using(var client = new SGSClient()) {
var model = new CashSessionCreateModel()
{
ClientType = ClientType.DesktopBrowser,
CurrencyCode = "EUR",
GameReferenceId = "netent_es_starburst",
LossLimit = 100,
SessionReferenceId = "f39dc178-279e-4e3a-bda9-a16829eb0e45"
};
HttpResponseMessage response = client.PostAsJsonAsync(apiUrl, model).Result;
}
Adding HTTPClient configuration:
public SGSHttpClient()
{
var appSettingsFilePath = $"Configuration\\appSettings.json";
// Build Configuration
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile(appSettingsFilePath, false, true)
.AddEnvironmentVariables()
.Build();
var sgsConfig = configuration.GetSection("SGSClient");
//Base url for SGS service
var _clientConfig = sgsConfig.GetSection("Client").GetChildren();
var baseAddress = _clientConfig.FirstOrDefault(o => o.Key.Equals("BaseAddress"));
BaseAddress = new Uri(baseAddress.Value);
//Adding headers
DefaultRequestHeaders.Accept.Clear();
DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
_dateUTC = DateTime.UtcNow.ToString("u");
DefaultRequestHeaders.Add("DateUtc", _dateUTC);
}

This and one other SO question were the only useful pages I found when I was scratching my head over this same issue today. Neither question had satisfactory explanations though. So after some more head scratching, I was able to set my mind at ease. Hopefully my answer on the other question explains the behavior to your satisfaction!
tl;dr
PostAsJsonAsync uses JsonContent which uses Transfer-Encoding: chunked instead of Content-Length and the "strange characters" are chunk headers (and perfectly valid HTTP/1.1)

You can use this type format to send may be helpfull
var postTask = client.PostAsJsonAsync<ClassNameOfObject>(baseUri + "ControllerName/ActionName?UserID=" + UserID, object);
postTask.Wait();

Related

TikTok api user/info/ endpoint return error code 6007063

I implemented TikTok PI and everything works well. In the last days I encountered a problem that the user/info/ endpoint returns 'error code': '6007063', 'message': 'auth user info is required'. This is happening for some of the accounts while others succeeded (there is nothing different between the accounts), I guess it's on tiktok side.
var Client = new HttpClient();
var userDataRequest = new UserDataRequest
{
open_id = tokenObj.data.open_id,
access_token = tokenObj.data.access_token,
fields = new HashSet<string> { "open_id", "union_id", "avatar_url", "avatar_url_100", "avatar_url_200", "avatar_large_url", "display_name" }
};
var json = JsonConvert.SerializeObject(userDataRequest);
var body = new StringContent(json, Encoding.UTF8, "application/json");
var response = await Client.PostAsync("https://open-api.tiktok.com/user/info/", body).ConfigureAwait(false);
How can I solve the problem and what does this error mean?
https://developers.tiktok.com/doc/login-kit-user-info-basic
I encountered the same issue and I found that the way I refresh the access token is incorrect. POST https://open-api.tiktok.com/oauth/refresh_token/
For this API, we should put client_key, grant_type, and refresh_token in the query instead of in the body or post data.
POST https://open-api.tiktok.com/oauth/refresh_token/?client_key={my_client_key}&grant_type=refresh_token&refresh_token={my_client_token}
This solves my problem. Maybe you could check the way you refresh your access token to solve this issue.
Indeed, all data should be in the link, and not in the body of the request. And then when receiving a token by reference https://open-api.tiktok.com/oauth/access_token/ it works correctly when using it further
Doc: https://developers.tiktok.com/doc/login-kit-manage-user-access-tokens/
let url_access_token = 'https://open-api.tiktok.com/oauth/access_token/';
url_access_token += '?client_key=' + CLIENT_KEY;
url_access_token += '&client_secret=' + CLIENT_SECRET;
url_access_token += '&code=' + code;
url_access_token += '&grant_type=authorization_code';

How are parameters passed through HttpClient in .NET Core

I am very, very new to the entire idea of REST and calling an API from http in general, but for a project I am working on, it has become necessary.
I am using ASP.NET Core, so I've been trying to find a REST library. When I was using standard .NET, I could use RestSharp, but the community made RestSharp.Core is pretty out of date and has many incompatibilities with newer versions of .NET Standard 1.6+.
To that end, I've explored other options, but my inexperience just makes it frustrating. Inevitably, I'm thinking it is best if I just use the built in HttpClient class. But I'm not sure how to do that for this exact scenario. I'm having a very hard time understanding how to give the parameters to the request, and what I'm specifically looking for in the return value.
My needs are pretty simple;
create a connection to $url
specify that it is a POST operation.
pass an existing JSON object to the server when making the request.
get JSON data back.
My code, using old RestSharp.Core, looks a bit like this - obviously keys and such omitted for privacy.
public async Task<string> OpenApiAsync() {
var token = await Task.Run(async () => {
var httpClient = new RestClient("https://[OMITTED].auth0.com/oauth/token");
var httpRequest = new RestRequest() {
Serializer = new RestSharp.Serializers.JsonSerializer(),
Method = Method.POST
};
httpRequest.AddHeader("content-type", "application/json");
httpRequest.AddJsonBody(new {
client_id = _settings.Value.ClientId,
client_secret = _settings.Value.ClientSecret,
audience = _settings.Value.Audience,
grant_type = _settings.Value.GrantType
});
var httpResponse = await httpClient.Execute(httpRequest);
var deserializer = new RestSharp.Deserializers.JsonDeserializer();
return deserializer.Deserialize<Dictionary<string, string>>(httpResponse);
});
return token["access_token"]);
}
The _settings object is injected with IOptions<Auth0Settings>, which has this shape and general data.
"authentication": {
"Domain": "[auth0-domain]",
"Audience": "https://[OMITTED].auth0.com/api/v2/",
"ClientId": "ABCDEFGHIJKLMNOP....",
"ClientSecret": "A22u5hgbnwifhwihfwi20u559f...",
"CallbackUrl": "http://localhost:5000/signin-auth0",
"GrantType": "client_credentials"
}
Can anyone help me understand how this could be ported to the native HttpClient that is in .NET Standard 1.6+? I specifically need one that is compatible with netstandard1.6 and netcoreapp1.1.
HttpClient is a very good http client and should be used in .NET core moving forward :)
private static async Task<string> OpenApiAsync()
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("content-type", "application/json");
var body = JsonConvert.SerializeObject(YOUR_BODY);
var result = await client.PostAsync("https://[OMITTED].auth0.com/oauth/token", new StringContent(body , Encoding.UTF8));
var deserialized = JsonConvert.DeserializeObject<Dictionary<string, string>>(await result.Content.ReadAsStringAsync());
return deserialized["access_token"];
}

SOAP service on Java returns incorrect types in Response

I use a third-party server written in Java.
WSDL is taken with the style of rpc/literal.
Connection to the service is initialized as follows:
private static MLPortChannel GetMerlionClient()
{
BasicHttpsBinding binding = new BasicHttpsBinding(BasicHttpsSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
binding.MaxReceivedMessageSize = 4096000;
EndpointAddress adress = new EndpointAddress(new Uri(#"https://apitest.merlion.com/rl/mlservice3"));
ChannelFactory<MLPortChannel> factory = new ChannelFactory<MLPortChannel>(binding, adress);
factory.Credentials.UserName.UserName = mlLogin;
factory.Credentials.UserName.Password = mlPassword;
return factory.CreateChannel();
}
It is works correctly only for one method and returns the correct data type and the data.
When I call other methods, they returns error as:
"Can not convert an object of type " ... MLService3RLTest.CatalogResult [] " of the type " ... MLService3RLTest.ShipmentDatesResult []"
In this example return type must be ShipmentDatesResult[].
I tested the service via special tool. All requests and responses is correct and returned correct XML.
What may be the cause of this error? Perhaps something needs to be configured for SOAP service. Maybe some magic option with right value?
If, instead of referring to the service, make a web link which uses the technology of web services .Net FrameWork 2.0 what works
var client = new WpfApplication1.com.merlion.apitest.MLService();
var myCredentials = new System.Net.NetworkCredential(Логин, Пароль);
// Create a webrequest with the specified URL.
var url = "https://apitest.merlion.com/rl/mlservice3";;
client.Credentials = myCredentials.GetCredential(new Uri(url), "Basic");
textBox.AppendText(client.helloWorld("Привет"));
var ответ = client.getCatalog("N1");
var массив = new string[] { "" };
var rz = client.getItems("N10100", массив, "", 0, 2, "");
add
client.PreAuthenticate = true;

What is the ASP.NET Core MVC equivalent to Request.RequestURI?

I found a blog post that shows how to "shim" familiar things like HttpResponseMessage back into ASP.NET Core MVC, but I want to know what's the new native way to do the same thing as the following code in a REST Post method in a Controller:
// POST audit/values
[HttpPost]
public System.Net.Http.HttpResponseMessage Post([FromBody]string value)
{
var NewEntity = _repository.InsertFromString(value);
var msg = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Created);
msg.Headers.Location = new Uri(Request.RequestUri + NewEntity.ID.ToString());
return msg;
}
In an ASP.NET Core MVC project, I can't seem to get Request.RequestUri.
I tried inspecting Request, and I was able to make a function like this:
private string UriStr(HttpRequest Request)
{
return Request.Scheme + "://" + Request.Host + Request.Path; // Request.Path has leading /
}
So I could write UriStr(Request) instead. But I'm not sure that's right. I feel like I'm hacking my way around, and not using this correctly.
A related question for earlier non-Core ASP.NET MVC versions asks how to get the base url of the site.
Personally, I use :
new Uri(request.GetDisplayUrl())
GetDisplayUrl fully un-escaped form (except for the QueryString)
GetEncodedUrl - fully escaped form suitable for use in HTTP headers
These are extension method from the following namespace : Microsoft.AspNetCore.Http.Extensions
A cleaner way would be to use a UriBuilder:
private static Uri GetUri(HttpRequest request)
{
var builder = new UriBuilder();
builder.Scheme = request.Scheme;
builder.Host = request.Host.Value;
builder.Path = request.Path;
builder.Query = request.QueryString.ToUriComponent();
return builder.Uri;
}
(not tested, the code might require a few adjustments)
Here's a working code. This is based off #Thomas Levesque answer which didn't work well when the request is from a custom port.
public static class HttpRequestExtensions
{
public static Uri ToUri(this HttpRequest request)
{
var hostComponents = request.Host.ToUriComponent().Split(':');
var builder = new UriBuilder
{
Scheme = request.Scheme,
Host = hostComponents[0],
Path = request.Path,
Query = request.QueryString.ToUriComponent()
};
if (hostComponents.Length == 2)
{
builder.Port = Convert.ToInt32(hostComponents[1]);
}
return builder.Uri;
}
}

How to add a request header in Nancyfx?

I tried adding this in the bootstrapper in the ApplicationStartup override.
pipelines.AfterRequest.AddItemToStartOfPipeline(ctx =>
{
ctx.Request.Headers["x-fcr-version"] = "1";
});
Its giving me errors.
Can anyone point me in the right direction?
Notice how you are trying to set the Request while trying to manipulate the Response ?
Try this..
protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
{
base.RequestStartup(container, pipelines, context);
pipelines.AfterRequest.AddItemToEndOfPipeline(c =>
{
c.Response.Headers["x-fcr-version"] = "1";
});
}
This is what my Response looks like..
Or .. you can use Connection Negotiation if you're going to set it at the module level...
Get["/"] = parameters => {
return Negotiate
.WithModel(new RatPack {FirstName = "Nancy "})
.WithMediaRangeModel("text/html", new RatPack {FirstName = "Nancy fancy pants"})
.WithView("negotiatedview")
.WithHeader("X-Custom", "SomeValue");
};
Since this question is about adding headers to a nancy request, which I need to do as I need to add an origin header, and some others when making requests to my app api.
In order to get it to work, I did the following:
//create headers dictionary
var myHeaders = new Dictionary<string, IEnumerable<string>>();
myHeaders.Add("origin",new List<String>{"https://my.app.com"});
//..... snip - adding other headers ....//
var uri = new Uri("https://my.api.com");
var request = new Nancy.Request("OPTIONS", uri, null, myHeaders,"127.0.0.1", null);
I found reading the nancy request source source useful, as the null parameters, (body and protocolVersion) and I passed through get initialized if not set.
For some reason the answer with content negotiation is not working in my case but I found another way:
Get["result"] = x=>
{
...
var response = Response.AsText(myModel, "application/json");
response.Headers.Add("Access-Control-Allow-Origin", "http://example.com");
response.Headers.Add("Access-Control-Allow-Credentials", "true");
return response;
};

Categories

Resources