I have a xamarin android app that makes requests to an api hosted on .net core (on IIS on Windows Server). Initial requests ALWAYS take a long time to load (presumably because of some warmup process). How do I ensure that the API is ready to go by the time the user needs to make a request?
Do I just make rapid async get/post requests on app startup? This seems in-efficient...
You need to use health check for your API:
public class ExampleHealthCheck : IHealthCheck
{
public ExampleHealthCheck()
{
// Use dependency injection (DI) to supply any required services to the
// "warmed up" check.
}
public Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default(CancellationToken))
{
// Execute "warmed up" check logic here.
var healthCheckResultHealthy = true;
if (healthCheckResultHealthy)
{
return Task.FromResult(
HealthCheckResult.Healthy("The check indicates a healthy result."));
}
return Task.FromResult(
HealthCheckResult.Unhealthy("The check indicates an unhealthy result."));
}
}
Add your service to health check services:
public void ConfigureServices(IServiceCollection services)
{
services.AddHealthChecks()
.AddCheck<ExampleHealthCheck>("example_health_check");
}
In Startup.Configure, call UseHealthChecks in the processing pipeline with the endpoint URL:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseHealthChecks("/health");
}
Link to documentation: https://learn.microsoft.com/ru-ru/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-2.2
Related
I have my startup class configured like this:
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCaching();
...
}
public void Configure(IApplicationBuilder app)
{
app.UseResponseCaching();
...
}
And my controller is like this:
[HttpGet]
[ResponseCache(Duration = 30)] //I normally have a policy here but used duration as an example
[Authorize("Policy_1")]
[Authorize(LocalApi.PolicyName)]
public IActionResult Get()
{
...
}
If I add a breakpoint on my controller method and use postman to send a request the breakpoint is hit and I can see the Cache Control key within the response headers:
If I send the request again the breakpoint IS hit (within the duration).
However, if I remove the Authorize attributes and the auth token from my request everything works as expected.
The authentication and authorization have been set up using identity server 4.
And just to confirm 'Send no-cache header' is off within postman.
So, the question is what do I need to add to get response caching working with identity server 4?
I have a requirement to start a process on the server that may run for several minutes, so I was thinking of exposing the following hub method:-
public async Task Start()
{
await Task.Run(() => _myService.Start());
}
There would also be a Stop() method that allows a client to stop the running process, probably via a cancellation token. I've also omitted code that prevents it from being started if already running, error handling, etc.
Additionally, the long-running process will be collecting data which it needs to periodically broadcast back to the client(s), so I was wondering about using an event - something like this:-
public async Task Start()
{
_myService.AfterDataCollected += AfterDataCollectedHandler;
await Task.Run(() => _myService.Start());
_myService.AfterDataCollected -= AfterDataCollectedHandler;
}
private void AfterDataCollectedHandler(object sender, MyDataEventArgs e)
{
Clients.All.SendData(e.Data);
}
Is this an acceptable solution or is there a "better" way?
You don't need to use SignalR to start the work, you can use the applications already existing framework / design / API for this and only use SignalR for the pub sub part.
I did this for my current customers project, a user starts a work and all tabs belonging to that user is updated using signalr, I used a out sun library called SignalR.EventAggregatorProxy to abstract the domain from SignalR. Disclaimer : I'm the author of said library
http://andersmalmgren.com/2014/05/27/client-server-event-aggregation-with-signalr/
edit: Using the .NET client your code would look something like this
public class MyViewModel : IHandle<WorkProgress>
{
public MyViewModel(IEventAggregator eventAggregator)
{
eventAggregator.Subscribe(this);
}
public void Handle(WorkProgress message)
{
//Act on work progress
}
}
I have a Socket handler in Vert.x and I know how to send data through the EventBus in a client-to-server (from Web Browser to Web Server) and server-component-to-server-component fashions.
Now I have a JavaFX-Client connected to the Vert.x Socket handler through websockets:
public void start() {
vertx.createHttpClient()
.setHost(Main.SOCKET_SERVER)
.setPort(8080)
.connectWebsocket("/chat/service", new Handler<WebSocket>() {
#Override
public void handle(WebSocket websocket) {
ws = websocket;
websocket.dataHandler(new Handler<Buffer>() {
#Override
public void handle(Buffer data) {
System.out.println("Received Data");
}
});
//...
// use ws for authentification
ws.writeTextFrame("doAuthentification");
//...
}
}
}
The Socket is connected to "/chat/service".
Now I want to use this Websocket to call different Services from Vert.x. I know that EventBus is not working from JavaFX-Client.
On the server:
ws.dataHandler(new Handler<Buffer>() {
#Override
public void handle(final Buffer data) {
String text = data.toString();
if(text.contentEquals("doAuthentification")){
logger.info("doAuthentification()");
doAuthentification();
}
// ...
}
}
I can now send "commands" like doAuthentification through the WebSocket, then, on server side and when that command is received, I can use the EventBus to process it further.
What would be the correct way using it from a client. Ideas?
Since you application is packaged as a standalone application is not deployed as in a Vert.x instance, you won't be able to call the event-bus since it is a Vert.x specific feature.
Your method to go would be, as you already tyried, to communicate to your Vert.x application in a standard way, through socket, or http for example (I would recommend HTTP and a RESTful application style), and send messages through an entry point that will be later on transferred to the appropriate verticles.
You may need to configure many path based handlers, maybe using a regex capture group inside, and let each handler choose the appropriate schema to delegate events, instead of having a single handler based on hardcoded messages.
My WCF Webservice provide all data manipulation operations and my ASP .Net Web application present the user interface.
I need to pass user information with many wcf methods from ASP .Net app to WCF app.
Which one in is better approach regarding passing user info from web app to web service?
1) Pass user information with SOAP header?
ASP .Net Application has to maintain the number of instances of WCF Webservice client as the number of user logged in with the web application. Suppose 4000 user are concurrently active, Web app has to maintain the 4000 instances of WCF webserice client.
Is it has any performance issue?
2) Pass user information with each method call as an additional parameter?
Every method has to add this addtional paramter to pas the user info which does not seems a elegant solution.
Please suggest.
regards,
Dharmendra
I believe it's better to pass some kind of user ID in a header of every message you send to your WCF service. It's pretty easy to do, and it's a good way to get info about user + authorize users on service-side if needed. And you don't need 4000 instances of webservice client for this.
You just need to create Behavior with Client Message Inspector on client side(and register it in your config). For example:
public class AuthClientMessageInspector: IClientMessageInspector
{
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
request.Headers.Add(MessageHeader.CreateHeader("User", "app", "John"));
return null;
}
}
public class ClientBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
foreach (var operation in endpoint.Contract.Operations)
{
operation.Behaviors.Find<DataContractSerializerOperationBehavior>().MaxItemsInObjectGraph = Int32.MaxValue;
}
var inspector = new AuthClientMessageInspector();
clientRuntime.MessageInspectors.Add(inspector);
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
And extract it from your service-side:
var headers = OperationContext.Current.IncomingMessageHeaders;
var identity = headers.GetHeader<string>("User", "app");
I searched a lot about implementing WebSocket/XMPP on Spring MVC based server but couldn't reach to a concrete answer. So here is my requirement
Receive a message from a client (in my case it will be a android/iOS mobile) via WebSocket/XMPP on tomcat server and parse the actual message at server side
Send a message from server app to WebSocket/XMPP client
If somebody could help me to point on some good tutorial or demo code, it would be a great help.
run Tomee 1.5.2
http://openejb.apache.org/downloads.html
activate the ActiveMQ JMS Server. create an OpenEJB configuration.
http://www.mail-archive.com/users#openejb.apache.org/msg04327.html
setup an XMPP ActiveMQ server protocol listener (in the activemq.xml)
in your Spring services configuration, create a Spring JMS listener (Spring ListenerContainer) configuration on the Topic/Queue.
you can use the JmsTemplate to push a message out to the Queue/Topic via ActiveMQ, the XMPP client will receive the message.
Enjoy!
BTW: This is exactly what I am in the middle of setting up right now...still learning.
check this out: www.xchat.io. It was built based on Asynchronous Spring MVC (DefferredResult, you know), XMPP, and jQuery. it's promising.
I am not sure if this is just perfect way to achieve or not, but for now I have found a solution and it would be glad to share it here.
There are two steps that you have to done.
1. Instead of ordinary HTTPServlet sub class, create a sub class of WebSocketServlet and
2. Create a sub class of MessageInbound class and override its required methods.
P.S. : Only latest version of tomcat supports WebSocket (apache tomcat 7.0.42 or higher).
Here is a WebSocket class.
public class WsChatServlet extends WebSocketServlet {
private static final long serialVersionUID = 1456546233L;
#Override
protected StreamInbound createWebSocketInbound(String protocol,
HttpServletRequest request) {
return new IncomingMessageHandler();
}
}
And this is a simple class which can send/receive message (String/binary).
public class IncomingMessageHandler extends MessageInbound {
#Override
public void onOpen(WsOutbound outbound) {
logger.info("Open Client.");
}
#Override
public void onClose(int status) {
logger.info("Close Client.");
}
#Override
public void onTextMessage(CharBuffer cb) throws IOException {
logger.info("Text Message received:" + cb.toString());
}
#Override
public void onBinaryMessage(ByteBuffer bb) throws IOException {
}
public synchronized void sendTextMessage(String message) {
try {
CharBuffer buffer = CharBuffer.wrap(message);
this.getMyoutbound().writeTextMessage(buffer);
this.getMyoutbound().flush();
} catch (IOException e) {
// Handle Exception
}
}
}