Hi all I use apache's httpclient to make restcalls, everything is working fine, When multiple thread are using this method my app crashes.
What is the implementation for this class that is MultithreadSafe.
Here is my code.
httpClient = new HttpClient();
HttpMethod method = null;
method = new GetMethod();
... method creation...
httpClient.executeMethod(method);
method.releaseConnection();
Thanks in advance. Juan
Have you looked at the HttpClient threading documentation ?
To get started one must create an instance of the
MultiThreadedHttpConnectionManager and give it to an HttpClient. This
looks something like:
MultiThreadedHttpConnectionManager connectionManager =
new MultiThreadedHttpConnectionManager();
HttpClient client = new HttpClient(connectionManager);
The issue you're having is quite common when using HttpClient out-of-the -box
Related
Im using this line to consume the API post method
var postTask = client.PostAsJsonAsync("AgregarNegocio", new StringContent(JsonConvert.SerializeObject(model).ToString(), Encoding.UTF8, "application/json"));
however when the API method is hit
public IActionResult AgregarNegocio([FromBody]NegocioViewModel model)
all the properties in model are null...
i already tried with and without [FromBody] and other solutions but none has worked yet, any suggestions?, thanks!
You need to construct your http client like this:
_client = new HttpClient { BaseAddress = new Uri("your http://my base url goes here"),
Timeout = new TimeSpan(0, 0, 0, 0, -1) };
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));//add json header
//_client.DefaultRequestHeaders.Add("Bearer", "some token goes here");
and you need to call your method like this:
var postTask = await _client.PostAsJsonAsync("AgregarNegocio", model);
make sure you call "await" on it because it is async.
NOTES:
Notice that I added MediaTypeWithQualityHeaderValue to indicate that it is json.
Also using Route usually is not a good idea... It is better to use HttPost("MyRoute") because it combined the ControllerName + Route. But it is up to you.
Try to use PostAsync instead of PostAsJsonAsync
var postTask = await client.PostAsync("AgregarNegocio", new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json"));
You can use the HttpClient extension method :
https://learn.microsoft.com/en-us/previous-versions/aspnet/hh944682(v=vs.118)
PostAsJsonAsync(
this HttpClient client,
string requestUri,
T value
)
var postTask = client.PostAsJsonAsync<NegocioViewModel>("AgregarNegocio", model);
You can use PostAsync but also do not forget about using HttpClient in right way as i described in this article.
Im building a new app and since i want it to be smooth as everyone, I want to use a background thread that would be responsible for all the data downloading using restsharp. Im also following the MVVM pattern.
I've been reading a lot about task.run and how to use it properly and the whole async-await topic. But since Im new to all this, Im not sure how I should procceed to do things right. I have a lot of code so I will breifly try to explain what Im doing and then put a snippet.
So I started with creating a service class that contains all the functions that are using restsharp to get the data. And inside my ViewModel Im calling those functions in the very begining. Im trying to use tasks and run those functions on the background thread but the app get blocked on the splash screen. And abviously thats because Im doing things wrong ... so I decided to ask you guys.
I have this function for exemple :
public string GetResPor()
{
var restClient = new RestClient { BaseUrl = new Uri("http://xxx.xxx.xxx.xxx:xxxx") };
var request = new RestRequest
{
Resource = "getCliPor",
Method = Method.GET
};
request.AddParameter(new Parameter { Name = "idt", Value = GetImAsync().GetAwaiter().GetResult(), Type = ParameterType.GetOrPost });
var result = restClient.Execute(request);
Port = result.Content;
return Port;
}
When I convert this on a Task :
public async Task<string> GetResPor()
{
var restClient = new RestClient { BaseUrl = new Uri("http://xxx.xxx.xxx.xxx:xxxx") };
var request = new RestRequest
{
Resource = "getCliPor",
Method = Method.GET
};
request.AddParameter(new Parameter { Name = "idt", Value = GetImAsync().GetAwaiter().GetResult(), Type = ParameterType.GetOrPost });
var result = await restClient.ExecuteTaskAsync(request);
Port = result.Content;
return Port;
}
on the ViewModel I start by creating a new instance of my service class and then:
Port = RD.GetRestauPort().GetAwaiter().GetResult();
And this is where the app get blocked, no exceptions no nothing.
To keep things simple, let's start with the basics. The easiest thing to do, in order to run something in a background thread, is to call it inside a Task.Run(). What this does is:
Queues the specified work to run on the ThreadPool and returns a task or Task<TResult> handle for that work.
Basically, you are delegating your work to the TreadPool and it handles everything for you - looks for a worker, waits for the worker to finish its job (on a new thread) and then notifies you of the result.
So, basically, whatever you want to be in a background thread, the simples solution will be to wrap it inside a Task.Run() and await its result, in case you need it.
Also, avoid using GetAwaiter().GetResult(). The simple rule in asynchronous programming is - if you can await, await all the way up.
You can read more about the topics in
this SO post
Advanced Tips for Using Task.Run With Async/Await
Using Task.Run in Conjunction with Async/Await
I'm using NEST to index my objects and I'm running into a Newtonsoft error on serialization. One of my objects has a self referencing loop. Would there be a way for me to access the JsonSerializer and change how it handles self-references without having to modify the source code?
You can register custom converters on your client:
public void AddConverter(JsonConverter converter)
{
this.IndexSerializationSettings.Converters.Add(converter);
this.SerializationSettings.Converters.Add(converter);
}
This might be of help.
There is no direct way to alter the JsonSerializerSettings used in the client though.
There is a new api now, take a look at:
var cs2 = new ConnectionSettings(new Uri("http://localhost:9200"))
.SetJsonSerializerSettingsModifier(settings => settings.TypeNameHandling = TypeNameHandling.None)
.EnableTrace();
Thanks for adding the support!
I am trying to query my local Solr server using HttpClient and I cannot figure out why the parameters are not being added to the GET call.
My code for doing this is:
HttpRequestBase request = new HttpGet("http://localhost:8080/solr/select");
HttpParams params = new BasicHttpParams();
params.setParameter("q", query);
params.setParameter("start", String.valueOf(start));
params.setParameter("rows", String.valueOf(rows));
request.setParams(params);
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();
return stringToStreamConversion(is); //500 error, NullPointerException, response is empty
I have tried to return several things in hopes of seeing what I would get and trying to figure out where the problem was. I have finally realized that I was only getting back the http://localhost:8080/solr/select when I returned
return request.getURI().toURL().toString();
I cannot figure out why the parameters are not getting added. If I do
return request.getQuery();
I get nothing back...any ideas? Thanks for the help in advance!
From what I have seen you are not able to associate your paeans with the request.
So, instead of creating a new HttpParams object and associating it with request, can you try the following approach ?
httpCclient.getParams().setParameter("q", query");
....
The simpler option is to use the approach I used in HTTPPostScheduler, like this:
URL url = new URL(completeUrl);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("type", "submit");
conn.setDoOutput(true);
// Send HTTP POST
conn.connect();
I have a WCF service that needs to know the Principal of the calling user.
In the constructor of the service I have:
Principal = OperationContext.Current.IncomingMessageHeaders.GetHeader<MyPrincipal>("myPrincipal", "ns");
and in the calling code I have something like:
using (var factory = new ChannelFactory<IMyService>(localBinding, endpoint))
{
var proxy = factory.CreateChannel();
using (var scope = new OperationContextScope((IContextChannel)proxy))
{
var customHeader = MessageHeader.CreateHeader("myPrincipal", "ns", Thread.CurrentPrincipal);
OperationContext.Current.OutgoingMessageHeaders.Add(customHeader);
newList = proxy.CreateList();
}
}
This all works fine.
My question is, how can I avoid having to wrap all proxy method calls in the using (var scope...{ [create header and add to OperationContext]?
Could I create a custom ChannelFactory that will handle adding the myPrincipal header to the operation context? Something like that would save a whole load of copy/paste which I'd rather not do but I'm not sure how to achieve it:)
Thanks
The correct time to set a WCF principal is via IAuthorizationPolicy, by specifying a custom policy in configuration. This covered in full here. If you try setting the principal at other points (an inspector, perhaps) it can get reset by the system.