Mediatr: Send common command (query) object and get object response

Created on 24 Mar 2019  ·  21Comments  ·  Source: jbogard/MediatR

Pleace add such functionality:

object query  = Activator.CreateInstance(requestType);
object response = Mediator.Send(query);
if(response is SomeType resp) 
{
 //...
}

Most helpful comment

Oh, I was waiting for a PR. @twadrianlis go ahead and open one!

All 21 comments

Why? What's your use case here?

For sending all requests from frontend and automatic detect Requests and send them.
Then to send a response.

I want to a send all requests from one place (action) without extending web API controllers, but in busines logic.
In controllers 2 actions: for Queries, and for Commands

For example in Nhibernate ORM (or EF) to get any entity i must know only its id and entityName:

object id='1234';
string entityName = 'SomeEntityClass';
object entity = dbSession.get(entityName,id);

I want something like this, but not in databases, but in business logic

How would the single controller know how what request type to use, and how would fill it with data? Would the data in the requests come from HTTP request information?

Its simple. From json
The query class will create using Json.Net lib or manually via Activator

//js
var httpPayload= {
  __type:'SomeDataQuery',
  id:'1234'
}
axios.get('url',httpPayload).then(resp=>console.log(resp))

I think in SPA apps it will be very usefull

That's how you instantiate it - but where will the properties on the request come from? JSON.Net? So you'd deserialize from JSON.NET into a request object?

yes using JSON.Net in this case.

I'm not sure about your use case - it sounds a bit like gRPC, and I'm not sure that it's worth all that just to avoid controllers.

But, Publish has an overload that is object-based for a different use case, so it would make sense to create one for Send. I'll take a pull request if you want to give this a shot.

Ok Thanks.

@megafetis we do this today without needing a object based send method. If you change your json object that is deserialized to something like this:

public class QueryWrapper
{
    public IRequest Query { get; set; }
}

then your json would just look like this:

{
    "Query": { "__type": "SomeDataQuery", "id": 1234
}

since you are using the __type property it will retain the correct type and the object will know it is an IRequest and .Send(...) will work just fine. You may even be able to remove the wrapper layer and simply have your controller accept an IRequest parameter instead of an object.

@megafetis we do this today without needing a object based send method. If you change your json object that is deserialized to something like this:

public class QueryWrapper
{
    public IRequest Query { get; set; }
}

then your json would just look like this:

{
    "Query": { "__type": "SomeDataQuery", "id": 1234
}

since you are using the __type property it will retain the correct type and the object will know it is an IRequest and .Send(...) will work just fine. You may even be able to remove the wrapper layer and simply have your controller accept an IRequest parameter instead of an object.

What about a response of request ? Unit or object, or another Type

var resp = _mediator.Send(query as IRequest);

Thank you, I'll try to do the same

Hmm now that I think of it we might have done this only for commands and not queries so everything had a return type of Unit. Even with a Send method that takes object how will you know what the response is? Or will it just be object as well?

Hmm now that I think of it we might have done this only for commands and not queries so everything had a return type of Unit. Even with a Send method that takes object how will you know what the response is? Or will it just be object as well?

I want just serialize object resp to http response in this case.
In other cases we can handle response if it implements some interfaces for example.. Or do other logic

It would be:

c# Task<object> Send(object request, CancellationToken cancellationToken = default);

Yes

@jbogard are you still accepting PR for the non-generic Send? I would use such a functionality and it is always better to have it officialy supported than to maintain a fork. I did however had a small problem and I am not sure if it will be a decent enough solution. I can prepare a PR and open it up for further discussion/guides on how to proceed with this.

I must warn you though, my main field is C++ not C# 😂

Edit: I have made something like this: https://github.com/jbogard/MediatR/compare/master...twadrianlis:non-generic-send

Let me know if this makes sense - I can open a PR is its close to what you expect.

@jbogard pleace apply non-generic Send, suggested above from @twadrianlis =)

Oh, I was waiting for a PR. @twadrianlis go ahead and open one!

the extension in the PR works nice though

public static class MediatorExtensions
    {
        public static async Task<object> Send(this IMediator mediator, object request, CancellationToken cancellationToken = default)
        {
            return await mediator.Send((dynamic)request, cancellationToken);
        }
    }

the extension in the PR works nice though

public static class MediatorExtensions
    {
        public static async Task<object> Send(this IMediator mediator, object request, CancellationToken cancellationToken = default)
        {
            return await mediator.Send((dynamic)request, cancellationToken);
        }
    }

I have been doing this for years in one of our (plugin extendable) webservices.

  • Have a registry of command names + .NET types. (plugins can register new command names + their type)
  • on http request of a command, lookup it's .NET type by command name
  • use JSON deserializer to deserialize to that type
  • because it's all runtime, you get back an 'object' from the serializer,
  • using that MediatR extension I send the command (object) to mediatr

Works like a charm

Yes, have the same case (command from json deserialization) glad I found
this thread ✌️

On Fri, Aug 23, 2019, 12:05 Remco Ros notifications@github.com wrote:

the extension in the PR works nice though

public static class MediatorExtensions
{
public static async Task Send(this IMediator mediator, object request, CancellationToken cancellationToken = default)
{
return await mediator.Send((dynamic)request, cancellationToken);
}
}

I have been doing this for years in one of our (plugin extendable)
webservices.

  • Have a registry of command names + .NET types. (plugins can register
    new command names + their type)
  • on http request of a command, lookup it's .NET type by command name
  • use JSON deserializer to deserialize to that type
  • because it's all runtime, you get back an 'object' from the
    serializer,
  • using that MediatR extension I send the command (object) to mediatr

Works like a charm


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/jbogard/MediatR/issues/385?email_source=notifications&email_token=AABIDT7Y7ZO4VQIKTGCF7G3QF6Y67A5CNFSM4HAVKB62YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD47YLSQ#issuecomment-524256714,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AABIDT2WID52U6N2PCQNVO3QF6Y67ANCNFSM4HAVKB6Q
.

Was this page helpful?
0 / 5 - 0 ratings