我应该如何在asp.net Web服务中存储对象,以便业务对象可以引用该对象?

时间:2010-08-09 18:26:46

标签: web-services logging object asmx

我正在构建一个将在我公司内部使用的ASP.NET Web服务。异常和跟踪/审计日志记录将由Web服务类以及Web服务将调用的业务对象执行。日志记录由内部开发的日志助手类的实例处理。日志助手必须是跟踪状态的实例,以及用于将日志消息关联到组中的引用guid。

在过去,我们通过使用方法参数将对日志帮助器实例的引用从类传递给类来处理这种情况。我试图找到一种可靠的方法来找到一种方法来存储和访问整个调用中的实例,而不必明确传递它。

我试图在Web服务调用的早期阶段将实例存储在HTTPContext中。当我的业务对象稍后在调用期间需要它时,它们将作为我的所有对象继承的基类的属性来访问它。

最初我尝试将实例存储在Web服务的Context.Cache中。这似乎有效,我的研究让我相信Cache是​​线程安全的。直到我开始从超过3个并发会话调用Web服务时,记录器的实例才会从调用到呼叫共享,而不是为每个调用重新创建新的。我尝试了Context.Application,发现了与Cache存储非常相似的结果。

我能够使用Context.Session找到看起来像是可用的解决方案。这要求我在每个方法的属性中使用EnableSession = true,但它似乎确保每个调用的实例都是唯一的。我不需要在调用之间跟踪数据,因此我不会在会话空间中存储会话cookie。

会话是否是我需要的最佳存储点?鉴于我不需要跟踪呼叫之间的会话,这似乎有点重。我愿意接受建议或批评。我相信有人会建议使用内置的跟踪日志记录或像Elmah这样的系统。那些可能是未来的选择,但现在我没有时间走这条路。

更新:我应该澄清这项服务需要在.Net Framework 2.0上运行。我们正在迁移到3.5 / 4.0但我们当前的生产服务器是Win2000,最大值为2.0。

3 个答案:

答案 0 :(得分:2)

您可以尝试使用OperationContext.Current。这将使您能够存储Web服务调用生命周期的变量。

编辑广告可能没有WCF解决方案: 由于您没有WCF,因此可以通过为对象创建线程ID的静态映射来创建类似线程本地存储的内容。只需确保在请求完成时正确清理此静态映射,否则使用该线程的下一个调用将拾取您的对象。此外,请确保在访问地图时锁定地图。

答案 1 :(得分:1)

我认为,在过去,您在Windows窗体应用程序中使用过这些业务对象?

您不应该让业务对象依赖于某些环境对象。相反,您应该使用构造函数注入属性注入将logger对象传递给业务对象。记录器应该由接口表示,而不是由具体类表示。应该将业务对象传递给实现此接口的某个类的引用。他们应该从不知道这个对象的存储位置。这将使您能够测试Web服务之外的业务对象。

然后,您可以将记录对象存储在任何您喜欢的位置。我建议将它存储在HttpContext.Current.Items中,它只对当前请求有效。


public interface ILogger
{
    void Log(string message);
}

public class Logger : ILogger
{
    public void Log(string message) {}
}

public class BusinessObjectBase
{
    public BusinessObjectbase(ILogger logger)
    {
        Logger = logger;
    }

    protected ILogger Logger {get;set;}
}

public class BusinessObject : BusinessObjectBase
{
    public void DoSomething()
    {
        Logger.Log("Doing something");
    }
}

答案 2 :(得分:0)

我的理解是为每个调用实例化ASMX类。因此,您似乎可以在ASMX的构造函数中实例化您的log-helper类,并将其存储在实例变量中。 ASMX类中的所有处理都将引用该实例变量。这样,在单个Web服务调用的整个生命周期中将使用相同的日志助手实例,并且不会在多个调用之间共享。

这很可能是在一个公共超类中实现的,所有ASMX类都将从该超类继承。虽然我想没有什么能阻止你在每个ASMX类中反复实现它,如果由于某种原因你避开了一个共同的超类。