I have played around with the Miniprofiler recently. It works fine in our application, and have found some interesting things we're working on.
However, I have a use case, where I need to make a custom injection with a record, where I can set the duration.
In the picture below, you can see the "hack" I've made to show it right now, but I'd like it to show correctly:
My situation
I am consuming a third party API. Every single page has a lot of calls, and is called from different views.
The API has a .NET client, which has a delegate that's called after it's dine:
private static void LogApiRequest(string httpMethod, string url, TimeSpan duration)
The issue is this method obviously is just used for logging, but I'd like to inject a duration here.
Any idea how to do it? :-)
if I understood well, just surround your API's calls with the following code:
ApiClient thirdPartyClient = new ApiClient();
using (profiler.Step("Calling third party API Methods"))
{
thirdPartyClient.MethodX();
}
Or, using custom categories:
ApiClient thirdPartyClient = new ApiClient();
using(MiniProfiler.Current.CustomTiming("3rd Party API","API.MethodY")
{
thirdPartyClient.MethodY();
}
Related
System.Text.Json 7.0 has provided the new and long awaited interface IJsonTypeInfoResolver. In this nice article one can find several helpful examples.
The problem appears when I try to register it in my Web API application.
I have my MyJsonTypeInfoResolver service which is scoped, which is dependent on another scoped service, which in turn is dependent on the third scoped service.
When I try doing like this
builder.Services.ConfigureOptions<ConfigureJsonOptions>();
builder.Services.AddScoped<IJsonTypeInfoResolver, MyJsonTypeInfoResolver>();
class ConfigureJsonOptions : IConfigureOptions<JsonOptions>
{
private readonly IJsonTypeInfoResolver _jsonTypeInfoResolver;
public ConfigureJsonOptions(IJsonTypeInfoResolver jsonTypeInfoResolver)
{
_jsonTypeInfoResolver = jsonTypeInfoResolver;
}
public void Configure(JsonOptions options)
{
options.JsonSerializerOptions.TypeInfoResolver = _jsonTypeInfoResolver;
}
}
I get the very standard error
Cannot consume
scoped service 'System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver' from singleton 'Microsoft.Extensions.Options.IOptions`
1[Microsoft.AspNetCore.Mvc.JsonOptions]'.
which I completely understand.
Playing with the second scope similar to what Andrew Lock shows in his article doesn't give me the expected result as I get into the issue that the second scoped service responds with the same result which is also expected but not what I need.
It looks like I'm missing smth obvious, however this is how it is. Will appreciate any help on this.
I'd like to setup a page that continuously receives values from the backend, so that the rendered data set grows with time until the backend says it's done (which may even never happen). Something like in this article but with backend based on .NET Core.
So, the Angular service looks like this at first.
#Injectable()
export class TheService {
constructor(private httpClient: HttpClient) {}
getStuff(): Observable<Thing[]> {
return this.httpClient.get<Thing[]>('http://localhost:3000/stuff');
}
getThing(): Observable<Thing> {
return this.httpClient.get<Thing>('http://localhost:3000/thing');
}
}
The issue I'm having is on the backend side. When I return the set of things, I finish off with providing Ok() specifying that the operation has completed successfully, status code 200. Now, what I'd like to achieve is to return a single thing at a time (or an array of things, as long as it's not the final set of all things to be served). Basically, I'd like to emit values from .NET API without finalizing the connection. For simplicity, we can even work with responses of type String instead of Thing.
Is it possible at all using "the usuals" in .NET? I'm thinking the default GET method like so.
[HttpGet("stuff")]
public ActionResult<IEnumerable<Thing>> GetThing()
{
IEnumerable<Thing> output = ...;
return Ok(output);
}
[HttpGet("thing")]
public ActionResult<Thing> GetThing()
{
Thing output = ...;
return Ok(output);
}
I've googled the matter but found nothing of relevance. There's a lot of resources dealing with the Angular side and observables, RxJs etc. All the examples connecting .NET and Angular present serve-and-finalize type of connection. The best one I've found is linked at the top and doesn't use .NET on the back. Somehow, I'm getting the suspicion that it's extremely simple or nearly not doable.
If you need a long-lived connection between client and server you could look into using WebSockets through something like Pusher, which has a .NET lib available: https://github.com/pusher/pusher-http-dotnet
Alternatively you could use long-polling, although that is much less efficient because you're intermittently querying the server for updates. You'd basically setup an Interval observable to make a request every N seconds to check for updates on the server.
I have a loop in my application that loops through a set of entities in the following fashion
foreach(var entity in mEntities)
{
entity.Update();
}
Some of these entities maintain a networking component that will call a Azure Mobile Service in order to update their state to the server. An example is below:
public class TestEntity {
public int Index;
public int PropertyValue;
public async void Update()
{
Task.Run(() => {
MyAzureMobileServiceClient.Update(Index, PropertyValue);
});
}
}
The UI rendering is done by Monogame in a more traditional game loop fashion. Whilst I do not know the inner workings of it, I am fairly certain that it does not have an actual separate thread doing the work. In practice, this shows as the UI freezing every time this update is called.
I want to be able to run it "smoothly" in the background. In the old Windows model this could have easily been done by starting a new Thread that would handle it, but I don't understand the threading well enough in WinRT to understand what is wrong with my approach.
Any ideas?
[update] I also tried this:
Task.Factory.StartNew(async () =>
{
while(true) {
await Task.Delay(1000);
MyAzureMobileServiceClient.Update(Index, PropertyValue);
}
});
Every 1 seconds, I get a mini-freeze like before.
[update 2] I tried this with a twist. I replaced the Azure Mobile Service client call with a standard HTTP request and it worked splendidly; no mini-freezes. Granted it wasn't to the backend yet, but at least I have a work around by doing the whole thing manually. Would prefer to not do that, however.
[update 3] This is getting peculiar. I realize I simplified the code in this question in order to get it coherent in the context. However, this appears to have removed the true source of the problem. I tried the following things:
I created a HTTP request and created the request manually, called it inside the Task.Run() and it worked splendidly with no latency.
I called the Azure Mobile Service client Update DIRECTLY and there was no latency.
So this brings me to where the problem lies. I basically have a wrapper class for the Azure Mobile Service. The real path that goes looks roughly like this:
CommunicationClient.UpdateAsync(myObject);
public Task UpdateAsync(MyObjectType obj)
{
var table = mMobileServiceClient.GetTable<MyObjectType>();
return table.UpdateAsync(obj);
}
This causes the lag, but if I do this instead of it, it works with no latency whatsoever:
var client = CommunicationClient.MobileServiceClient;
var table = client.GetTable<MyObjectType>();
table.UpdateAsync(obj);
Soooooo... I should probably refactor the whole question. It's getting tl;dry.
I had a question about how to run things on a backgroundthread and they advised me to use ThreadPool so I would advise you to look at my question and the answer on it maybe you can pick up on some things and get it working on your end.
Create Backgroundthread Monogame
Most of the examples I've found for SignalR are assuming ASP.NET (MVC or not). I'm using NancyFX. I'm having just one problem, so I'm hoping there's something I'm overlooking or some thing I need to do in Nancy to compensate for not being ASP.NET.
My one goal is to be able to notify the client browsers when a server event happens. I don't plan on replacing my Nancy routes with hub methods. But I would like the ability to call into the browser from my routes (actions).
I have very simple Hub that I created following the example in the SignalR Wiki. I'm not even sure I need it, since I don't plan on calling client to server.
public interface IUserNotifier
{
void Start();
void Notify(object #event);
}
I used an interface in hopes that I would be able to inject the same hub later on to use in my nancy routes... I'm not sure that is in the cards.
[HubName("userNotifier")]
public class UserNotifier : Hub, IUserNotifier
{
public void Start()
{
Notify(new {Status = "Started"});
}
public void Notify(object #event)
{
Clients.notification(#event);
}
}
When I have the following code in my html file, I can see that it executes the Start() method, and then the Notify() method, delivering content to my client.
var communicator = $.connection.userNotifier;
$.extend(communicator, {
Notification: function(event) {
alert("notification received from server!");
console.log(event);
}
});
$.connection.hub.start()
.done(function() {
communicator.start();
});
Like I said, "starting" the hub works and sends a notification to the client. Very cool. But, then, my primary goal hasn't been accomplished yet. I need to initiate these notifications from other places in my code where they might not be directly associated with a "request".
I tried injecting my IUserNotifier in my nancy modules for use in the routes, but when the Notify() is fired, I get:
That's because the Clients property on the Hub base class is null (hasn't been initialized). So, I switched gears. I tried to follow multiple examples, including the example from the wiki page about hubs in the section called "Broadcasting over a Hub from outside of a Hub":
public class NotifierModule : NancyModule
{
public NotifierModule(){
Get["/notify/{message}"] = p => {
var context = GlobalHost.ConnectionManager.GetHubContext<UserNotifier>();
context.Clients.notification(new { Message = p.message });
};
}
}
My Nancy route executes without throwing errors. Except my browser never receives the message. If I set a breakpoint in the route, I can see that Clients is initialized. Maybe the collection of clients is initialized but empty. Who knows? Maybe you do. :)
Again, my main goal is to be able to send events/notifications to the browser from anywhere in my code, any time. Is that too much to ask? What should I be doing here?
I'm sure you must have found the answer already. However, I figured I could try and help out in case anyone else runs into a similar problem. In order for your server on the .NET side to send messages to clients, it would also need to have a connection made to the hub.
var connection = new HubConnection("http://localhost/");
connection.Start();
connection.Notify("Hello");
Check out an official example at:
https://github.com/SignalR/SignalR/blob/master/samples/Microsoft.AspNet.SignalR.Client.Samples/Program.cs
Sorry for stupid question,
I just want to pass a JOSN string to the webpage in the webbrowser from my VB/C# code,
and can the javascript in webpage call the VB/C# method through some interface ?
Just like android javascript interface, many thanks
If I understand you correctly,
webBrowser2.ObjectForScripting = new ScriptClass();
webBrowser2.DocumentText = "<html><script>window.external.Test('hello')</script></html>";
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class ScriptClass
{
public void Test(string msg)
{
MessageBox.Show(msg);
}
}
So you're using a WebBrowser control and need to call a JavaScript method within the page it shows? Yeah, you can do this. It's not on the WebBrowser itself, but the HtmlDocument object, exposed by the WebBrowser's Document property, has an InvokeScript() method group, which will allow you to programatically invoke any ECMAScript-compliant method within the DOM of the page, optionally passing a series of parameters as an Object array.
That, in turn, can be used to trigger a call from JavaScript to a JSON web service (which you expose in your main CLR program, and told the page about by passing it the info via InvokeScript()). This is basic JSON/AJAX client-server scripting, all wrapped up into a single program talking to itself. It's not the most efficient way to get things done, but if you already have these layers that get the job done, and just want to release a self-contained app, it works.