How to change http.sys web server response when maxconnection limit reached - c#

We are using http sys web server to host web api service. Business requires to limit maximum number of concurrent connections. MaxConnections configuration property used for that purpose:
services.Configure<HttpSysOptions>(options =>
{
options.MaxConnections = Configuration.GetValue<long?>("MaxConnections");
});
But in case when concurrent connection limit reached all new connections got dropped on a socket level. Is it possible to change this behaviour so server accepts the request and returns 4xx or 5xx response to the client?

I have finally managed to find a solution: there is Http503Verbosity property in options. By default it is set to Http503VerbosityLevel.Basic but if to change it to Http503VerbosityLevel .Limited or Http503VerbosityLevel.Full 503 response will be returned for requests above limit. So my code looks like this now:
services.Configure<HttpSysOptions>(options =>
{
options.MaxConnections = Configuration.GetValue<long?>("MaxConnections");
options.Http503Verbosity = Http503VerbosityLevel.Full;
});

Related

Can I call a WCF endpoint from ASP.Net Web API?

I have a web api with controller methods that use rest http(post/get calls).
Clients consume this API with normal httpclient calls and I pass an http response back.
My use case is I have a legacy method that needs to make a call to another server. This method currently uses WCF and contract binding but I don't want to use WCF in this API project.
Is there a way that I can still call these methods using just WEB API or do I have to mix architectures (Web api with WCF)?
Here is the normal method call
First I initialize the proxy
var proxy = GetAccountProxy();
public static AcountClient GetAccountProxy()
{
var client = new AccountClient();
client.ClientCredentials.ClientCertificate.SetCertificate(...);
return client;
}
I connect to a method on the other server through the proxy
var accountInfo = proxy.GetAccountInfo(xmlAccount);
public string AccountInfo(string sXml){
AccountLookup val = new AccountLookup();
val.Body = new AccountLookupRequestBody();
val.Body.XML = sXML;
AccountLookupResponse retVal = ((AccountLookupResponse)(this)).AccountLookup(val);
return retVal;
}
In my webconfig the endpoints look like this
<endpoint address="https://www.mylookup.com/AccountLookupWS/AccountLookupWS.svc/wshttp" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IAccountLookupWS" contract="AccountLookupWS.IAccountLookupWS" name="WSHttpBinding_IAccountLookupWS1" />
So my question is can I just call this endpoint using a normal rest httpclient call and have the same result?
Uri baseUrl = new Uri("https://www.mylookup.com/AccountLookupWS/AccountLookupWS.svc/wshttp");
IRestClient client = new RestClient(baseUrl);
IRestRequest request = new RestRequest("GetAccountInfo", Method.GET)
request.AddParameter("XmlAccount", sXml);
IRestResponse<dynamic> response = client.Execute<dynamic>(request);
if (response.IsSuccessful)
{
response.Data.Write();
}
else
{
Console.WriteLine(response.ErrorMessage);
}
Console.WriteLine();
In general it is possible to access wcf with webrequest, but it depends on the wcf service implementation. Check out the WebGet and/or WebInvoke attributes https://learn.microsoft.com/en-us/dotnet/api/system.servicemodel.web.webgetattribute?view=netframework-4.8 and start from there.
It is work to be done on WCF side, after it is done properly, you can access your wcf as normal rest services.
It depends on your WCF server bindings. You see, HTTP/s protocol implementation is just possible module of WCF, a part, just like any other protocol out there - it is just called binding. Different bindings means same bindings should be on client side, otherwise they don't understand each other.
For example if server tells:
use gzip on my data which I send over wire
then I xor my data with 666 if first bit is set true
then use SSL to protect it
then send it over TCP
Then client should do the same thing in reverse. This is WCF and it's flexibility for you which opened hell gates for researchers and developers.
As I said, if your server supports HTTP bindings, without extra stuff - you are good. Use http client or billion other HTTP classes. If not - port your server protocol bindings to NET Core and use them.

Timeout exception - c# ( wcf )

While I'm executing the server method asynchronously, getting this Timeout exception continuously.
"Additional information:
This request operation sent to http://schemas.microsoft.com/2005/12/ServiceModel/Addressing/Anonymous
did not receive a reply within the configured timeout (00:01:00).
The time allotted to this operation may have been a portion of a longer timeout.
This may be because the service is still processing the operation or
because the service was unable to send a reply message.
Please consider increasing the operation timeout
(by casting the channel/proxy to IContextChannel and setting the OperationTimeout property)
and ensure that the service is able to connect to the client."
Could someone mention how to increasing the operation timeout
by casting the channel/proxy to IContextChannel and setting the OperationTimeout property ?
This is my existing binding (with client) code.
DuplexChannelFactory<IPortal> datafactory;
NetTcpBinding tcpBinding = new NetTcpBinding();
String sURL = "net.tcp://localhost:8002/MyPortal";
tcpBinding.MaxReceivedMessageSize = System.Int32.MaxValue;
tcpBinding.ReaderQuotas.MaxArrayLength = System.Int32.MaxValue;
datafactory = new DuplexChannelFactory<IPortal>(this,tcpBinding, sURL);
Portal = datafactory.CreateChannel();
If you follow the link in the error (schemas.microsoft.com etc etc) it serves up:
Theresource you are looking for has been removed, had its name
changed, or is temporarily unavailable.
Why are you looking up MS? It sounds like you've got some config data wrong somewhere. If you search your source for that url, what do you find? Does it look sensible?

How to inject Http Parser into OWIN Self host server

I have http clients that are sending "POST" requests with no contents which cause the selfhost server to throw http 411 error , the http clients are for customers that it is not a solution to modify them , so the only way to modify my server to not throw this error when "POST" request arrive without content .
it seem it is happening in the low level , no attribute or filter or even app.Use worked to catch the request before the error get thrown
it mostly happening at the next level when TCP content get converted to HTTP request.
So basically I am looking for the point when before the server parse the TCP contents into HTTP request
static void Main(string[] args)
{
var baseAddress = new Uri("http://localhost:8073");
var config = new HttpSelfHostConfiguration(baseAddress);
config.Routes.MapHttpRoute("default", "{controller}");
using (var svr = new HttpSelfHostServer(config))
{
svr.OpenAsync().Wait();
Console.WriteLine("Press Enter to quit.");
Console.ReadLine();
}
}
It turned out the HTTP parser is not inject-able, it is kind of limitation in my openion to any http server , as the trip of data from TCP client until it get converted to HTTP request is black boxed at least in OWIN self host server

ClientBase EndPoint Binding SendTimeout ReceiveTimeout: how to change while debugging

I'm developing a solution with a WCF service and a client that uses the service. Sometimes I'm debugging the service, sometime the client, and sometimes both.
During debugging I get a TimeoutException with additional information
Additional information: The request channel timed out while waiting for a reply after 00:00:59.9950000. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout.
The reason if of course that my server is waiting at a breakpoint instead of answering the question.
During debugging I want longer timeouts, preferably without creating a new configuration for my service client, because if other values of this configuration would change, the changer would have to remember that a special configuration for debugging was created.
I think it is something like:
private IMyServiceInterface CreateServiceChannel()
{
var myServiceClient = new MyServiceClient(); // reads from configuration file
if (Debugger.IsAttached)
{
// Increase timeouts to enable slow debugging
...
}
return (IMyServiceInterface)myServiceClient;
}
According to MSDN Binding.SendTimeout Property is used for something else:
SendTimeout gets or sets the interval of time provided for a write operation to complete before the transport raises an exception.
Therefore I'd rather not change this value if not needed.
Is SendTimeout really the best timeout to increase, or is there something like a TransactionTimeout, the timeout between my question and the receipt of the answer?
How to change the timeout programmatically
The article All WCF timouts explained states that indeed there is something like a transaction timeout: IContextChannel.OperationTimeout
The operation timeout covers the whole service call (sending the request, processing it and receiving a reply). In other words, it defines the maximum time a service call is active from a client’s point of view. If not set, WCF initializes the operation timeout with the configured send timeout.
This explains why the TimeoutException that is thrown advises to change the send timeout.
However, it is possible to change the operation timeout without changing the send timeout:
var myServiceClient = new MyServiceClient(); // reads from configuration file
if (Debugger.IsAttached)
{ // Increase timeouts to enable slow debugging:
IContextChannel contextChannel = (IContextChannel)myServiceClient.InnerChannel;
// InnerChannel is of type IClientChannel, which implements IContextChannel
// set the operation timeout to a long value, for example 3 minutes:
contextChannel.OperationTimeout = TimeSpan.FromMinutes(3);
}
return (IMyInterface)myService;

Pipelining using HttpWebRequest in C#

I am working on an HTTP client which should ideally pipeline requests when needed. Also, the requests will be sent on specific network interfaces (the client is multihomed).
Asynchronous sockets are used and in order to make a request, I use the following code:
Uri url = new Uri(reqUrl);
ServicePoint sp = ServicePointManager.FindServicePoint(url);
sp.BindIPEndPointDelegate = new BindIPEndPoint(localBind);
pseg.req = (HttpWebRequest)HttpWebRequest.Create(url);
pseg.req.AddRange("bytes", psegStart, psegStart + psegLength - 1);
pseg.req.KeepAlive = true;
pseg.req.Pipelined = true;
For each request made using this code, a separate connection to the server is opened and segments received in parallell. This is ok, however, it is not the behavior I want. I want the requests to be pipelined, but the replies to arrive sequentially. If I use locking or set the connectionlimit to 1, the request for segment #2 is not sent until after segment #1 has been fully received.
Is there any way to achieve what I want and still use the HttpWebRequest/Response-classes? Or will I have to drop down to sockets?

Categories