How do I implement subscriptions in GraphQL HotChocolate? - c#

I am implementing HotChocolate as part of my ASP.NET API. I'm trying to add subscriptions to the chat portion on my app, however, the documentation on the HotChocolate site is not implemented yet. From what I can tell from other sites/frameworks, I can use the C# IObservable<Chat> as the return type for the subscription method.
Can anyone give me an example of a query method or point me towards another resource?
public async Task<IObservable<Message>> GetMessages(Guid chatId) {
var messages = ..Get chats;
return messages;
}
However, how does this work from a query standpoint? How do we trigger an event to update this?
Thanks.

Since the original documentation link became obsolete I am posting this new link that refers to our workshop project.
Chapter 7 shows how to do subscriptions in two variants.
https://github.com/ChilliCream/graphql-workshop/blob/master/docs/7-subscriptions.md
I hope that helps.

Related

Language component in URL of default Identity UI for asp.net 6

I have an application which I must port to asp.net 6. I try to implement the authentication logic with scaffolded default identity UI pages.
The application uses URLs which start with a path component which holds the user’s language, then followed by the concrete path components. Something like:
/{language}/product/{product}
Now I try to establish this url schema also with the asp.net identity default UI pages. For example, the login page url should be look something like this:
/en/login
/fr/login
/it/login
However, up to now I had only little success in doing so. In changing the #page directive in the scaffolded pages I was able to introduce the {language} path component. However, how do I now tell the cookie middleware to integrate the current {language} placeholder into the redirect? Something like this:
builder.Services.ConfigureApplicationCookie(options =>
{
options.LoginPath = "/{language}/Login";
});
Is this feasible in some way or another or is there even a more solid way to accomplish the goal?
Update
Up to now I came up with a solution and posted it as an answer, since it works. However if anybody knows a more sophisticated approach, please post it, I feel that the way I did this is really ugly and I cannot believe that there is no cleaner way to accomplish this, since also Microsoft uses the Url schema I try to implement in their websites.
One possibility I've found is to use the CookieAuthenticationOptions.Events-instance. This seems a feasible way, however it seems to me extremely brutish and one has to register to every event which is concerned and every scaffolded page has to be changed (redirects etcetera).
However, as long as no other solution is provided, this may help someone:
builder.Services.ConfigureApplicationCookie(options =>
{
options.LoginPath = "/language/Login";
options.Events.OnRedirectLogin=>(context){
// here would stand some Ajax-checks ...
var myLanguage= ... // detection of the language from the query string
context.Response.Redirect(context.RedirectUri.Replace("/language/", myLanguage));
}
});
The above code is best refactored in a new class which derives from CookieAutenticationEvents, where then proper handling can be done for each event. So the only assigment in the Program.cs file is the assignment of the custom authentication events class. The original class seems a bit quirky and depending on the purpose of the derived class, it is either better to initially assign custom events while constructing the instance or to override the methods which raise the assigned event handlers.
Within the pages, the language can be declared via the page directive:
#page "/{language}/login"
#page "/{language}/loginWith2fa"
etcetera
The code behind then will be changed, for example the signature of the get and set method will be extended with the language-parameter.
public async Task<IActionResult> OnGetAsync(string language,bool rememberMe, string returnUrl = null) {
and additionally, any url references in the code behinds must be changed. Since this way is so ugly, I tried to completely abstain from the default identity ui. In this post I ask for a way to do so.

Blazor Parameter Object or child API call or Virualization?

I am working on a project that includes a list of Help Articles.
Clicking on an Article in the list opens the Article.
OnInitializedAsync() calls to the API for the Article.include(Comments).theninclude(Replies).
I have a CommentList component that builds the comment list using instances of Comment component
Each Comment has a ReplyList component that builds a reply list using instances of Reply component
The page is built:
Article API Call including Comments then Replies
CommentList [Parameter] public <ArticleDto> Article
Comment instances [Parameter] public <CommentDto> Comment
ReplyList [Parameter] public <ReplyDto> Reply
Reply instances [Parameter] public <ReplyDto> Reply
The page is slow to render with a lot of foreach and if checks so I'm left wondering if my approach is a bit immature?
If you've faced this dilemma, I'd love to hear what your approach was.
I'm considering having each list component make its own API call but I was hoping to avoid multiple calls to build a single page. Virtualization seems like a good candidate perhaps?

What is the best way to set up a Provider base-state using Pact.Net and .Net Core?

In the (Ruby) documentation of Pact, there is the possibility to add a Provider base-state in the provider states. I'm using Pact.Net and use ProviderStateMiddleware, but I can't figure out how to set up the base-state with this implementation. Is it possible to do this and/or does anyone have any experience setting this up?
Thanks in advance!
There is no built in functionality for a base state (that I know of - Neil Campbell, the maintainer, may correct me). I would recommend implementing a method that gets called at the start of each provider state set up call that clears the datastore completely, and then sets up the base state data.
Thank you for asking. I have recently started researching pact-net, and I am also interested in guidance.
I found this Example Workshop for .Net Core very helpful.
Supplementing the example ProviderMiddleware, we added something like the following (assuming relational db with EF):
private void EnsureBaseState()
{
_context.Database.EnsureDeleted();
_context.SaveChanges();
}
private void EnsureSecondState()
{
EnsureBaseState();
_context.ExampleItems.Add(new ExampleItem { Id = 1, Name = "sample item" });
_context.SaveChanges();
}
This is how we are currently managing multiple states, with the additional states calling a base state in the middleware.

Is there a built-in way to register only for specific topics?

I want to use signalR to broadcast events from my server to the client proxies.
The server uses the multi tenancy architecture and I want to seperate each tenant in the signalR-Hub by the signalR groups.
Furthermore I want to broadcast my "framework events" thru signalR. The client should register himself for the events he need.
Can this problem be covered by "signalR-Topics" or must the client register only the events he wants, like:
myHub.On<string>("addMessage", param => {
Console.WriteLine(param);
});
This sample has the restriction, that all events/methods must be defined on the server, and if the framework gets a new event, I also habe to add a new signalR method/event.
The other problem is: That if the client wants to unsuscribe from "addMessage"?
Is it possible to remove the registration "myHub.On("addMessage"..." while runtime?
An other idea:
That if I only publish "one" generic event-method, with an additional string parameter "topic". The clients can register on startup for specific "topics" and on the server-side it can be determined which clients get the event.
I would store the client/topic mapping in a dictionary.
var topciMapping = Dictionary<string, List<string>>;
//the key is the topic name, and the list contains the signalR connectionIds
The next question will be: Can I send events to a custom list of connectionIds?
This should do the trick, right?
var connectionIds = new List<string>();
Clients.Clients(connectionIds)
If you have the list of all connectionIDs you want to send the message to, you ca basically just do this:
foreach(var connectionId in ConnectionList)
Clients.Client(connectionId).sendMessage(message);
Hope this helps.
Best of luck!
The "other idea" makes absolutely sense. Note that there already is a possibility to address groups by name, which could very well suit your topics. That way you already have the users grouped that you can then easily address:
Clients.Group(groupName).addChatMessage(name, message);
Clients.OthersInGroup(groupName).addChatMessage(name, message);
Reference: Working with groups in SignalR
EDIT
The generic method is the way to go then. Also, the topic Dictionary makes sense based on what you said in the comment that you're already using groups. Also the addressing via Clients.Clients(connectionIds) should work.
So in general if you're asking if this is a decent approach, then I'd say yes. I couldn't find anything about "SignalR-Topics", wondering if I missed something.

Is there an equivalent of Java's Spring MVC style url mapping for C#/.NET?

I am looking for the C# equivalent of Spring MVC's url mapping using annotations, i.e in Java I can write:
#Controller
#RequestMapping("/some-friendly-url/")
class MyController
{
#RequestMapping(value = "/{type}/more-seo-stuff/{color}", method = RequestMethod.GET)
public List<SomeDTO> get(#PathVariable String type,
#PathVariable String color,
int perPage) {
...
}
#RequestMapping(method = RequestMethod.POST)
public String post(#RequestBody SomeDTO somethingNew) {
...
}
}
It's actually much more powerful than this simple example as anyone familiar the the concept knows.
I've tried to search on how to achieve the same with either ASP.MVC 3 or with MonoRail and both frameworks seem to be based on RoR's convention-over-configuration "//" philosophy and it would be hard to achieve the above with them and require a lot of bespoke routing entries outside the controller class with only a small subset of the functionality available via attributes. Spring.NET does not seem to address this either stating that ASP.MVC's routing functionality is sufficient.
Is there anything out there in the C# world that provides this type of functionality? I was just about to start looking into writing something of my own to address this, but I was hoping not to have to do that.
Edit: Finally found the "AttributeRouting" project which is available on NuGet as well: https://github.com/mccalltd/AttributeRouting/wiki/1.-Getting-Started. Works perfectly. Doesn't support to full range of features that Spring MVC does, but supports most of it.
Also Akos Lukacs pointed to another good library below by ITCloud. However that one unfortunately is not available on NuGet.
Sure, you can use Spring.NET:
http://www.springframework.net/
I Eventually used https://github.com/mccalltd/AttributeRouting/wiki/1.-Getting-Started. Posting this only now for the sake of keeping the question complete.

Categories