我有一个使用自定义usernamepasswordvalidator的WCF服务。验证器需要访问我的实体框架上下文。

我想为整个服务调用创建一个ObjectContext,然后在呼叫结束时销毁/将其丢弃。所以我创建了一个单身静态类,提供了这个功能,但是,现在正在发生的事情是,如果两个服务调用同时发生,其中一个呼叫处置单例。

我要么保留本地引用,要么将其使用它的第二个服务,它会将其视为设置并抛出和错误,或者,我在所有我需要的地方围绕单身级围绕单身级包装属性。更改被抛弃,因为如果另一个呼叫已经配置了该对象的新实例。

所以基本上我的问题是我如何实例化每个服务调用的ObjectContext?

注意:该实例需要在服务代码和自定义usernamepasswastvalidator代码中可接近。

我不能只在构造函数中执行或使用语句,因为自定义usernamepasswasswardator没有访问它。有没有办法每次呼叫拥有静态课程?它听起来不可能,但这遍布这一点是什么?我应该在会话中缓存对象吗?

我的服务在IIS中托管。

更新:
所以我用IExtension对象将此缩小到InstanceContext中的状态。但是如何在UsernamePasswordValidator中访问当前的InstanceContext?

有帮助吗?

解决方案

好的,所以最后我通过使用以下静态类来解决它并依赖于ASP.NET缓存我的上下文。

我不确定这是做事的最佳方式,但这允许我每请求使用一个ObjectContext,所以我没有旋转太多,这也意味着我不必使用锁定如果许多用户使用该服务,那将成为噩梦的对象。

public static class MyContextProvider
    {
        public static MyModel Context
        {
            get
            {
                if (HttpContext.Current.Items["context"].IsNull())
                {
                    HttpContext.Current.Items["context"] = new MyModel();
                }

                return HttpContext.Current.Items["context"] as MyModel;
            }
        }    
    }
.

然后我需要在应用程序中需要一个ObjectContext,我只需拨打

var context = MyContextProvider.Context;
.

其他提示

每个呼叫有一个实例,每个实例也有1个呼叫。

所以它应该非常简单,在TopleVel的TopleVel中使用using () { }块。

好的,这里是带有线程安全静态方法的类,为任何WCF服务调用提供单个objectext Entity模型对象,并在呼叫结束时自动将其分解:

public static class EntityModelProvider
{
    private static readonly Dictionary<OperationContext, MyEntityModel> _entityModels = new Dictionary<OperationContext, MyEntityModel>();

    public static MyEntityModel GetEntityModel()
    {
        if (OperationContext.Current == null)
            throw new Exception("OperationContext is missing");

        lock (_entityModels)
        {
            if (!_entityModels.ContainsKey(OperationContext.Current))
            {
                _entityModels[OperationContext.Current] = new MyEntityModel();
                OperationContext.Current.OperationCompleted += delegate
                {
                    lock (_entityModels)
                    {
                        _entityModels[OperationContext.Current].Dispose();
                        _entityModels.Remove(OperationContext.Current);
                    }
                };
            }

            return _entityModels[OperationContext.Current];
        }
    }
.

对于您的服务,您可以指定一个服务行为,详细说明服务的实例模式:

[ServiceBehaviour(InstanceContextMode = InstanceContextMode.PerCall)]
public class MyService : IMyService {
    ObjectContext context;
}
.

更清晰的方式可以使用ServiceAuthenticationManager,该管理员在.NET 4中。

http://msdn.microsoft.com/cn -us / library / system.servicemodel.serviceauthenticationmanager.aspx

Authenticate方法(您将覆盖),您可以访问消息对象并在其上设置属性。我没有用它愤怒,所以ymmv :)

编辑此方法的问题是您没有用户名和密码,所以仍需要自定义身份验证。

看看UserNameEcurityTokenauthenticator ... http:// msdn .microsoft.com / en-US / Library / System.identityModel.Selectors.UsernamesEecurityTokenauthenticator(v= vs.90).aspx


从我的研究进一步阅读:

这个问题的答案给出了一些关于如何使用它的提示:

使用system.servicemodel.serviceauthenticationManager? < / p>

如果可以读取(或忽略)俄语,我发现了有用的提示:

http://www.sql.ru/forum/actualthread.aspx ?TID= 799046

这个相当好的codeproject文章进一步(加密和压缩以及自定义授权)

http://www.codeproject .com /文章/ 165844 / wcf-client-server-products-with-custom-authenti

为什么在将上下文中传递到CustomValidator时分配给服务时 - 将您的对象上下文存储在验证器中,并且在覆盖验证方法中,如果需要。然后您仍然可以通过Services CutomuserNameValidator访问该对象..

取决于您要求的内容: 创建单独的ObjectContext类作为动态对象 - 将其添加为CustomValidator的属性。 在您的自定义验证器中 - 您现在可以检查对象是否被配置并再次创建对象。 否则,如果这不是您的追踪 - 只是将上下文存储在验证器中 - 您仍然可以在服务器端访问。 这里的代码只是概括的想法 - 我只是把它发布为一个参考框架,这样你就可以了解我在谈论的内容。

public DynamicObjectContextObjectClass
{
  ObjectContext internalObjectContext;

}
public class ServiceUserNamePasswordValidator : UserNamePasswordValidator
{

    public DynamicObjectContextObjectClass dynamiccontext;


    public override void Validate(string userName, string password)
    {
        if(dynamiccontext.internalObjectContext.isdisposed)
        {

        dynamiccontext.internalObjectContext = new Context;

            }
            try
            {
                if (string.IsNullOrEmpty(userName) || password == null)
                {
                    //throw new ArgumentNullException();
                    throw new FaultException("Username cannot be null or empty; Password cannot be null and should not be empty");
                }
       }
   }
} 
.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top