Session
中的Service
存在问题,第二次调用时Session
为null
(已解决,请参阅帖子底部)。
我有自托管服务器和客户端,通过JsonServiceClient
和ProtoBufServiceClient
拨打服务器。
在客户端应用程序启动时,我打电话:
var baseUrl = ConfigGlobal.Host ;
var client = new JsonServiceClient(baseUrl);
var authResponse = client.Post<AuthResponse>("/auth", new Auth
{
UserName = "test1",
Password = "password",
RememberMe = true
});
它有效 - OnAuthenticated
它在CustomUserSession : AuthUserSession
中被解雇了。
authService.SaveSession(session);
没有帮助。
然后在一个班级中:
var client = new ProtoBufServiceClient(ConfigGlobal.Host);
client.Put(new ExcelInitialize {Filename = ""}); // OK
Model = client.Get(...); // Session is null
Get
方法中的服务类存在问题,会话为null
。如果我实施
public CustomUserSession CustomUserSession
{
get
{
return SessionAs<CustomUserSession>();
}
}
我得到:只支持通过Singletons访问的ASP.NET请求。
container.Register<ICacheClient>(new MemoryCacheClient());
container.Register<ISessionFactory>(c => new SessionFactory(c.Resolve<ICacheClient>()));
Plugins.Add(new AuthFeature(
() => new CustomUserSession(), new IAuthProvider[]
{
new CustomCredentialsAuthProvider(),
new BasicAuthProvider(),
}));
Plugins.Add(new RegistrationFeature());
从客户端发送一些变量并在主机上记住它们,直到用户注销。
我的工作流程如下所示:
SomeClass1:
SomeClass2:
服务G:
服务E
My Custom *类看起来像Scott回答。
以下是我准备复制和粘贴的问题代码:
private static void Main(string[] args)
{
// Very basic console host
var appHost = new AppHost();
appHost.Init();
appHost.Start("http://*:8082/");
var url = "http://localhost:8082";
var foo = new TestApp.SomeClass1(url);
var bar = new TestApp.SomeClass2(url);
Console.ReadKey();
}
public class AppService : Service
{
public CustomUserSession CustomUserSession
{
get
{
// Returns the typed session
return SessionAs<CustomUserSession>();
}
}
}
public class GService : AppService
{
public object Get(GRequest request)
{
var client = base.TryResolve<EService>();
client.Get(new WRequest());
return new { CustomUserSession.SuperHeroIdentity };
}
}
public class EService : AppService
{
public void Get(WRequest wRequest)
{
Console.WriteLine(CustomUserSession.SuperHeroIdentity);
}
public void Get(ERequest request)
{
Console.WriteLine(CustomUserSession.SuperHeroIdentity);
}
public void Put(ERequest request)
{
Console.WriteLine(CustomUserSession.SuperHeroIdentity);
}
}
public class SomeClass1
{
public SomeClass1(string url)
{
var client = new JsonServiceClient(url);
client.Post<AuthResponse>("/auth", new Auth
{
UserName = "clark.kent",
Password = "kryptonite",
RememberMe = true
});
}
}
public class SomeClass2
{
public SomeClass2(string url)
{
var client = new JsonServiceClient(url);
client.Put(new ERequest());
client.Get(new GRequest());
}
}
public class GRequest : IReturnVoid
{
}
public class ERequest : IReturnVoid
{
}
public class WRequest : IReturnVoid
{
}
答案 0 :(得分:1)
您发布的代码看起来不错。因此,对您的设置来说,这可能是微不足道的。
我创建了一个简单的自托管应用,它也使用了CustomUserSession
和CustomCredentialsAuthProvider
,希望以此为指导将突出显示出错的地方。让我知道你是怎么过的。
using ServiceStack.CacheAccess;
using ServiceStack.CacheAccess.Providers;
using ServiceStack.ServiceInterface;
using ServiceStack.ServiceInterface.Auth;
using ServiceStack.ServiceHost;
using ServiceStack.WebHost.Endpoints;
namespace Testv3
{
class MainClass
{
public static void Main()
{
// Very basic console host
var appHost = new AppHost();
appHost.Init();
appHost.Start("http://*:8082/");
Console.ReadKey();
}
}
public class AppHost : AppHostHttpListenerBase
{
public AppHost() : base("Test Service", typeof(TestApp).Assembly) {}
public override void Configure(Funq.Container container)
{
// Cache and session IoC
container.Register<ICacheClient>(new MemoryCacheClient());
container.Register<ISessionFactory>(c => new SessionFactory(c.Resolve<ICacheClient>()));
// Register the Auth Feature with the CustomCredentialsAuthProvider.
Plugins.Add(new AuthFeature(
() => new CustomUserSession(),
new IAuthProvider[]
{
new CustomCredentialsAuthProvider(),
new BasicAuthProvider(),
})
);
}
}
public class CustomCredentialsAuthProvider : CredentialsAuthProvider
{
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
// Replace with a database lookup
return (userName == "clark.kent" && password == "kryptonite");
}
public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
{
var customSession = session as CustomUserSession;
if(customSession != null)
{
// Replace these static values with a database lookup
customSession.FirstName = "Clark";
customSession.LastName = "Kent";
customSession.SuperHeroIdentity = "Superman";
}
authService.SaveSession(customSession, SessionExpiry);
}
}
public class CustomUserSession : AuthUserSession
{
// Our added session property
public string SuperHeroIdentity { get; set; }
}
public static class TestApp
{
[Route("/SuperHeroTime", "GET")]
public class SuperHeroTimeRequest {}
public class TestController : Service
{
public CustomUserSession CustomUserSession
{
get
{
// Returns the typed session
return SessionAs<CustomUserSession>();
}
}
[Authenticate]
public object Get(SuperHeroTimeRequest request)
{
// Return the result object
return new { CustomUserSession.FirstName, CustomUserSession.LastName, Time = DateTime.Now.ToString(), CustomUserSession.SuperHeroIdentity };
}
}
}
}
如果您将此index.html
放入bin
文件夹并导航至http://localhost:8082/index.html
,则可以拨打该服务进行测试。
<!doctype html>
<html>
<head>
<title>Test</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
function login()
{
$.ajax({
type: "POST",
url: "/auth/credentials",
contentType: "application/json",
data: JSON.stringify({
UserName: "clark.kent",
Password: "kryptonite",
RememberMe: true
})
}).done(function(result){
getSuperHeroTime();
});
}
function getSuperHeroTime()
{
$.ajax({
type: "GET",
url: "/SuperHeroTime",
contentType: "application/json",
}).done(function(result){
$("#result").html(result.FirstName + " " +
result.LastName + " is " +
result.SuperHeroIdentity + " (" +
result.Time + ")");
});
}
</script>
</head>
<body>
<h1>Super Hero Time</h1>
<button onclick="login()">Go</button>
<div id="result"></div>
</body>
</html>
查看了编辑中提供的使用代码。您正在SomeClass1
中调用Auth方法,然后不会重用JsonServiceClient
。所以你的会话不会跟随。您必须重用客户端,因为客户端存储跟踪您的会话的cookie。
在SomeClass2
中,您实际上是在不进行身份验证的情况下调用服务,因此会话为null
。您需要为请求重复使用相同的JsonServiceClient
。
您可以运行身份验证方法,然后将会话cookie传递给任何后续JsonServiceClient
,以便为每个客户端保存重新身份验证。这很容易做到:
var authClient = new JsonServiceClient(url);
authclient.Post<AuthResponse>("/auth", new Auth {
UserName = "clark.kent",
Password = "kryptonite",
RememberMe = true
});
// Get the session cookies
var cookies = authClient.CookieContainer.GetCookies(new Uri(url));
// In your other `JsonServiceClient`s set the cookies before making requests
var anotherClient = new JsonServiceClient(url);
anotherClient.CookiesCollection.add(cookies);
anotherClient.Post( ...
您还尝试使用以下方法解析服务中的其他服务:
base.TryResolve<EService>();
您需要使用此功能,否则您将看到Only ASP.NET Requests accessible via Singletons are supported
例外:
base.ResolveService<EService>();