Async REST Services using WCF WebApi - wcf

I want to know what is the opinion of you fellow Developers regarding WCF WebApi services.
In an N-tier application we can have multiple layers of services. We can have services consuming data from external services. In that scenario its worth to create Async Rest Services using WCF 4.0.
public interface IService
{
[OperationContractAttribute(AsyncPattern = true)]
IAsyncResult BeginGetStock(string code, AsyncCallback callback, object asyncState);
//Note: There is no OperationContractAttribute for the end method.
string EndGetStock(IAsyncResult result);
}
But with the release of WCF WebApi this approach is still required? to create async services?
How to host them in IIS/WAS/Self Hosting
looking forward for suggestion and comments.

Well What i feel,In order to create asynchronous operations in the latest WCF WebAPIs (preview 6) I can still use same pattern (Begin/End), but I can also use the Task programming model to create asynchronous operations, which is a lot simpler.
One example of an asynchronous operation written using the task model is shown below.
[WebGet]
public Task<Aggregate> Aggregation()
{
// Create an HttpClient (we could also reuse an existing one)
HttpClient client = new HttpClient();
// Submit GET requests for contacts and orders
Task<List<Contact>> contactsTask = client.GetAsync(backendAddress + "/contacts").ContinueWith<Task<List<Contact>>>((responseTask) =>
{
return responseTask.Result.Content.ReadAsAsync<List<Contact>>();
}).Unwrap();
Task<List<Order>> ordersTask = client.GetAsync(backendAddress + "/orders").ContinueWith<Task<List<Order>>>((responseTask) =>
{
return responseTask.Result.Content.ReadAsAsync<List<Order>>();
}).Unwrap();
// Wait for both requests to complete
return Task.Factory.ContinueWhenAll(new Task[] { contactsTask, ordersTask },
(completedTasks) =>
{
client.Dispose();
Aggregate aggregate = new Aggregate()
{
Contacts = contactsTask.Result,
Orders = ordersTask.Result
};
return aggregate;
});
}
[WebGet(UriTemplate = "contacts")]
public Task<HttpResponseMessage> Contacts()
{
// Create an HttpClient (we could also reuse an existing one)
HttpClient client = new HttpClient();
// Submit GET requests for contacts and return task directly
return client.GetAsync(backendAddress + "/contacts");
}

WCF Web API comes with an completely async HttpClient implementation and you can host in IIS and also completely sefhost.
For a async REST "service" scenario please read "Slow REST"

Related

trying to Azure AD authentication with gRPC-Web using protobuf-net

I am trying to Azure AD authentication with gRPC-Web in a blazor webassembly app. I am using protobuf-net to help me with the serialization. I am not sure how to pass the token to have the server side recognize it. this is what I have:
var headers = new Metadata
{
{ "Authorization", $"Bearer {Token}" }
};
and, I am sending that as a parameter in the method I want to consume
var result = await Client.CreateCustomer(this.customer, headers);
This is how the service is injected:
builder.Services.AddTransient(services =>
{
var httpClient = new HttpClient(new GrpcWebHandler(GrpcWebMode.GrpcWeb, new HttpClientHandler()));
var channel = Grpc.Net.Client.GrpcChannel.ForAddress("****", new GrpcChannelOptions { HttpClient = httpClient });
return channel.CreateGrpcService<Application.Services.ICustomerService<ServerCallContext>>();
});
This is how the service is published:
endpoints.MapGrpcService<CustomerService>().RequireAuthorization().EnableGrpcWeb()
and, this is the implementation:
public class CustomerService : ICustomerService<ServerCallContext>
{
[Authorize]
public async ValueTask<Customer> CreateCustomer(Customer customerDTO, ServerCallContext context)
{****}
}
the error I am getting is cannot convert from 'Grpc.Core.Metadata' to 'Grpc.Core.ServerCallContext' which is kind of obvious.
The reference I have found uses Metadata but is ServerCallContext the one I am supposed to use https://learn.microsoft.com/en-us/dotnet/architecture/grpc-for-wcf-developers/metadata so what I am missing, what I am doing wrong, how to properly use both using protobuf-net?
It looks like the problem here is that you're using ServerCallContext in the method signature; the underlying gRPC core has separate client/server context APIs, but this is not amenable to use on an agnostic interface, and as such, protobuf-net.Grpc unifies these two APIs, via CallContext. So: instead of:
async ValueTask<Customer> CreateCustomer(Customer customerDTO, ServerCallContext context)
for the signature, consider:
async ValueTask<Customer> CreateCustomer(Customer customerDTO, CallContext context)
or
async ValueTask<Customer> CreateCustomer(Customer customerDTO, CallContext context = default)
The CallContext API exposes the common server-side and client-side APIs (headers, cancellation, etc) in a single way, or you can use (for example) context.ServerCallContext to get the server-specific API if needed (this will throw an exception if used on a client-context). For client-side usage, a CallContext can be constructed from a CallOptions, which is the core gRPC client-side API, for example:
var result = await service.CreateCustomer(customer, new CallOptions(headers));
I'm open to the idea of allowing CallContext to be created directly from Metadata / CancellationToken etc (allowing var result = await service.CreateCustomer(customer, headers);) - but it doesn't seem essential.

How to extend IdentityServer4 workflow to run custom code

I have a basic Identityserver4 implementation based on the quick start sample.
In my startup I have the following:
public void ConfigureServices(IServiceCollection services)
{
// configure identity server with in-memory stores, keys, clients and scopes
services.AddIdentityServer()
.AddTemporarySigningCredential()
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients());
}
public void Configure(IApplicationBuilder app)
{
...
app.UseIdentityServer();
}
I want to extend the IdentityServer4 workflow so that after the access token is generated I can run business logic (based on the claims in the access token) and modify the response send to the calling client. I tried creating a .NET core middleware but it seems the IdentityServer middleware short-circuits the rest of the pipeline (no middleware place after the UseIdentityServer will be executed).
Are they any extension method in Identityserver4 that I can use to always modify the response issued by IdentityServer4? I am using the credentials grant. Essentially I want to run some business logic to modify the response send to the client once IdentityServer4 is done with its workflow
Unfortunately, there is no way to do that.
When you request any IdentityServer endpoint, IdentityServer middleware short-circuits the rest of the pipeline.
You can check source code:
IdentityServerMiddleware class.
I believe it was done for a reason. But if you really need to modify the response, you have at least three options:
Create a fork and remove return operator from
IdentityServerMiddleware Invoke method (be careful to short-circuit the rest of the pipeline adding return into your last middleware).
Create your own IdentityServerMiddleware, IdentityServerApplicationBuilderExtensions implementations and use
them instead of default.
Place your middleware before the UseIdentityServer. Your middleware should look like this:
public ResponseBodyEditorMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
// get the original body
var body = context.Response.Body;
// replace the original body with a memory stream
var buffer = new MemoryStream();
context.Response.Body = buffer;
// invoke the next middleware from the pipeline
await _next.Invoke(context);
// get the body as a string
var bodyString = Encoding.UTF8.GetString(buffer.GetBuffer());
// make some changes
bodyString = $"The body has been replaced!{Environment.NewLine}Original body:{Environment.NewLine}{bodyString}";
// update the memory stream
var bytes = Encoding.UTF8.GetBytes(bodyString);
buffer.SetLength(0);
buffer.Write(bytes, 0, bytes.Length);
// replace the memory stream with updated body
buffer.Position = 0;
await buffer.CopyToAsync(body);
context.Response.Body = body;
}

Service Fabric Asp.net Core Kestrel HttpClient hangs with minimal load

I have a barebone Service Fabric Application hosting a Asp.net Core 1.1 Web API with Azure Application Gateway as reverse proxy on a Virtual Machine scale set of 5 DS3_V2.
The API have 10 HttpClients with different URLs injected via Dependency Injection.
A simple foreach cycle in a method call 10 Httpclients in parallel:
var cts = new CancellationTokenSource();
cts.CancelAfter(600);
//Logic for asyncronously parallel calling the Call method below
public async Task<MyResponse> Call(CancellationTokenSource cts, HttpClient client, string endpoint )
{
var endpoint = "finalpartOfThendpoint";
var jsonRequest = "jsonrequest";
try
{
var content = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
await content.LoadIntoBufferAsync();
if (cts.Token.IsCancellationRequested)
{
return new MyResponse("Token Canceled");
}
var response = await client.PostAsync(endpoint, content, cts.Token);
if (response.IsSuccessStatusCode && ((int)response.StatusCode != 204))
{
//do something with response and return
return MyResponse("Response Ok")
}
return MyResponse("No response")
}
catch (OperationCanceledException e)
{
return new MyResponse("Timeout");
}
}
There is a single CancellationToken for all calls.
After 600ms, the still pending HttpCalls are canceled and a response is sent back anyway.
In local and in production all works perfectly, all endpoints are called and return in time, rarely one is canceled before the timeout.
But when the number of concurrent connections reach 30+, ALL calls timeout no matter what, until I reduce the load.
Does Asp.net Core have a connection limit?
This is how I create the HttpClients in a custom factory for injection in the main Controller:
public static HttpClient CreateClient(string endpoint)
{
var client = new HttpClient
{
BaseAddress = new Uri(endpoint)
};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
return client;
}
All the Httpclients are reused and static.
The same exact code works perfectly on a Asp.net Web API 2 hosted on OWIN in Service Fabric. The problem is only with Asp.net Core 1.1
I saw online to create a HttpClientHandler, but there is no parameter for concurrent connections.
What can I do to investigate further?
No exception are thrown but the OperationcanceledException and If I remove the CancellationToken the calls are stuck and the CPU goes to 100%, basically 30 connections destroy the power of 5 quad core servers.
This has something to do to the number of calls going out of Kestrel.
UPDATE
I tried with WebListener and the problem is still present, so it's not Kestrel, but Asp.net Core
I figured it out.
Asp.net core still have some HttpClient limits for the connection to the same server like the old Asp.net WebAPI.
It's poor documented but the old ServicepointManager option for maxconnections must now be passed via HttpClientHandler.
I just create HttpClient like this and the problem vanished.
var config = new HttpClientHandler()
{
MaxConnectionsPerServer = int.MaxValue
};
var client = new HttpClient(config)
{
BaseAddress = new Uri('url here')
};
Really if someone of the team is reading, this should be the default.

Using Client-Side Task-Based Operations with WCFFacility in Castle.Windsor

I would like to take advantage of the new task-based operations for a WCF client. I am currently using the WCFFacility as follows:
container.Register(Component
.For<IAdminService>()
.LifeStyle.Transient
.AsWcfClient(new DefaultClientModel()
{
Endpoint = WCFHelpers.BasicHttp(settings.MaxReceivedMessageSize)
.At(addr)
}));
where IAdminService is the ServiceContract class. All the MSDN articles about task-based operations refer to setting a 'task based operations' tick box when importing the service reference. But in the style I am currently using, there is no imported service reference because I simple refer directly to the service contract interface.
So I am wondering how I can enable support for task-based operations with the least amount of changes to the current code.
[BTW - WCFHelpers is a utility class that generates a BindEndpointModel and addr is set up to an appropriate endpoint address prior to this code being executed]
The WCFFacility provides some extension methods that conform to the old async pattern. These can easily be converted to Tasks.
Try these extension methods:
public static class ClientExtensions
{
public static async Task<TResult> CallAsync<TProxy, TResult>(this TProxy proxy, Func<TProxy, TResult> method)
{
return await Task.Factory.FromAsync(proxy.BeginWcfCall(method), ar => proxy.EndWcfCall<TResult>(ar));
}
public static async Task CallAsync<TProxy>(this TProxy proxy, Action<TProxy> method)
{
await Task.Factory.FromAsync(proxy.BeginWcfCall(method), ar => proxy.EndWcfCall(ar));
}
}
In an async method they can be called like this:
// Func<T>
var result = await client.CallAsync(p => p.SayThisNumber(42));
// Action
await client.CallAsync(p => p.DoSomething());

How should I consume a WCF service using MVC3

I am writing a fairly simple MVC3 application that allows a user to retrieve and modify some configuration data held by a WCF service. The configuration data will not change very often but needs to be maintainable by the user.
Once the user is happy with the configuration, they will launch some processing from the UI or by the scheduled execution of a VB script.
I'm fairly new to WCF and even newer to MVC3 but I'd like to make all the comms to and from the service RESTful. Is this a good thing to do?
I'd been planning to perform the service communications from the MVC controller. This would make a HTTP Get request to retrieve the current configuration and a HTTP Post to apply the modified configuration. I'd also use a Get request to launch the processing.
Could anyone provide an example (or point me in the direction) of how I should be doing this?
Please follow the below links for some sample code to build a RESTful WCF Service and the how the client would access the service.
Link to create a RESTful service: here
Link to create a .NET client that consumes the RESTful service : here
Hope the information helps you out.
If you are the owner of web service, you can directly reference implementation of service in your mvc project and use it without web reference. You can write some like this:
// example of ws
public class Service1 : IService1
{
public string GetData( int value )
{
return string.Format( "You entered: {0}", value );
}
public CompositeType GetDataUsingDataContract( CompositeType composite )
{
if( composite == null )
{
throw new ArgumentNullException( "composite" );
}
if( composite.BoolValue )
{
composite.StringValue += "Suffix";
}
return composite;
}
}
// example of mvc action
public class HomeController : Controller
{
public ActionResult Index()
{
IService1 service = new Service1();
service.GetDataUsingDataContract(....)
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
}
The simplest answer I've found was here:, using the channel factory.
I still don't know if it's the best way but it left my code looking clean enough. Below is a sample from my controller.
public ActionResult Index()
{
SettingsModel config = null;
// Set up a channel factory to use the webHTTPBinding
using (WebChannelFactory<IChangeService> serviceChannel =
new WebChannelFactory<IChangeService>(new Uri(baseServiceUrl )))
{
IChangeService channel = serviceChannel.CreateChannel();
config = channel.GetSysConfig();
}
ViewBag.Message = "Service Configuration";
return View(config);
}