Gateway Upgrade Problem

In ServiceStack 5.02 , It works Fine, After Upgrade to 5.10, It occur a error like below.

my code to set the Gateway

public override void Configure(Container container)
    {
...
 container.Register<IServiceGateway>(GetNewClient()); 
}
protected virtual IJsonServiceClient GetClient() => new JsonServiceClient(f.ApiUrl);
    private string GetRefreshToken()
    {
        var authClient = GetClient();
        var refreshToken = authClient.Send(new Authenticate
        {
            provider = "credentials",
            UserName = '1111222',
            Password = '44555',
        }).RefreshToken;
        return refreshToken;
    }
 public JsonServiceClient GetNewClient()
    {
        var client = GetClient();
        var serviceClient = client as JsonServiceClient;
        if (serviceClient == null)  //JsonHttpClient doesn't implement OnAuthenticationRequired but it does implement the new Refresh Tokens support
            return null;
        serviceClient.OnAuthenticationRequired = () =>
        {
            var authClient = GetClient();
            serviceClient.BearerToken = authClient.Send(new GetAccessToken
            {
                RefreshToken = GetRefreshToken(),
            }).AccessToken;

            //To improve accessibility with Ajax clients JWT Tokens can also be sent using the ss-tok Cookie, e.g:
            //serviceClient.SetCookie("ss-tok", serviceClient.BearerToken);
            ////Equivalent to: 
            //serviceClient.SetTokenCookie(serviceClient.BearerToken);
        };
        return serviceClient;
    }

I’d need a stand-alone reproducible example (e.g. on GitHub) in order to be able to identify and resolve the issue.

I think it’s your add the code in the version 5.10 , why add it? no code below , my code works fine.

+            if (req == null)
 +                throw new ArgumentNullException(nameof(req));
 +

My Code

public class AppService : Service
{
}
public class Test
{
 protected virtual AppService AppService => HostContext.Resolve<AppService>();
private async void btnWeixinSyncTemplate_Click(object sender, EventArgs e)
        {
            using (var app = AppService)
            {
                var Gateway = app.Gateway;
                await Gateway.SendAsync(new SmsMessages{});
            }
       }
        public virtual IServiceGateway GetServiceGateway(IRequest req)
        {
            if (req == null)
                throw new ArgumentNullException(nameof(req));

            var factory = Container.TryResolve<IServiceGatewayFactory>();
            return factory != null ? factory.GetServiceGateway(req) 
                : Container.TryResolve<IServiceGateway>()
                ?? new InProcessServiceGateway(req);
        }

My Code not use IServiceGatewayFactory , Only Use IServiceGateway, So Don’t need IRequest, so check the req is null or not is not needed .

Most usages do need it and it was added because the default InProcessGateway requires a Request Context and it wasn’t obvious what the cause of the error was when null was provided.

You can resolve this in your Service by overriding in your AppHost that uses new BasicRequest() if no IRequest was passed in.

I’ve added an overload to call GetServiceGateway() without arguments in this commit.

This change is available from v5.1.1 that’s now available on MyGet.

my code is

container.Register<IServiceGateway>(GetNewClient()); 

how to overriding in your AppHost that uses new BasicRequest() if no IRequest was passed in.

I Have override the Gateway in my code , It works , thanks.

public class AppService : Service
{
 
    private IServiceGateway gateway;
    public override IServiceGateway Gateway => gateway ?? (gateway = HostContext.AppHost.GetServiceGateway(new BasicRequest()));
}
      public virtual IServiceGateway GetServiceGateway(IRequest req)
        {
            if (req == null)
                throw new ArgumentNullException(nameof(req));

            var factory = Container.TryResolve<IServiceGatewayFactory>();
            return factory != null ? factory.GetServiceGateway(req) 
                : Container.TryResolve<IServiceGateway>()
                ?? new InProcessServiceGateway(req);
        }

I think you check the req == null is too early, you can check it after factory != null, Container.TryResolve< IServiceGateway>() Don’t need Check the req.

      public virtual IServiceGateway GetServiceGateway(IRequest req)
        {
            var factory = Container.TryResolve<IServiceGatewayFactory>();
            if(factory != null)
           {
                 if (req == null)
                throw new ArgumentNullException(nameof(req));
             }
            var result = factory != null ? factory.GetServiceGateway(req) 
                : Container.TryResolve<IServiceGateway>();
           if(result == null)
          {
            if (req == null)
                throw new ArgumentNullException(nameof(req));
          }
            return    result ?? new InProcessServiceGateway(req);
        }

No it’s meant to be validated early so all Gateway providers are assured there will always be an IRequest and the cause of the error happens close to the call site and more readily identifiable. You can use the new overload to retrieve a Gateway without a Request.