.Net标准的自定义System.Web.HttpContext

时间:2019-02-10 19:41:30

标签: c# asp.net multithreading asp.net-core

我们有几个用.Net Framework编写的网站。 现在我们要转到.Net Core。 我们希望一个接一个地做,因此旧网站和新网站应该并存。 所有网站共享通用的dll,例如LoggerDll。

为了在两个网站(旧网站和新网站)中仅使用一个dll,我们将LoggerDll更改为.Net Standard,并从两个网站中添加对它的引用。

问题在于LoggerDll引用System.Web dll是为了获取用于写入日志的请求的IP(以及其他请求信息),而.Net Core中不存在。

例如:

public void WriteToLog(string message)
{
    //This line doesn't compile in .Net Core
    string userIp = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
    WriteToDB(message, userIp);
}

我不想将IP作为参数传递给WriteToLog,因为那样的话,我需要将其作为参数添加到所有调用它的方法中,并且在发生异常时几乎所有方法都调用WriteToLog。

所以我宁愿继续从某些“全局”对象获取请求信息,但应在.Net Core和.Net Framework中进行编译。

我想创建一个新类“ MyRequestInfo”,为其创建一个静态属性,然后在“ BeginRequest”事件中用数据填充它。

例如:

public class MyRequestInfo
{
    public string UserIp { get; set; }
}

public class MyRequest
{
    [ThreadStatic] \\ Is ThreadStatic is ok?
    public static MyRequestInfo ReqInfo { get; set; }
}

//Global.asax
protected void Application_BeginRequest(object sender, EventArgs e)
{
     MyRequest.ReqInfo.UserIp = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}

//LoggerDll
public void WriteToLog(string message)
{
    string userIp = MyRequest.ReqInfo.UserIp;
    WriteToDB(message, userIp);
}
  1. 这样的灵魂还可以吗?
  2. [ThreadStatic]是正确的还是我应该使用AsynLocal或其他?

谢谢

1 个答案:

答案 0 :(得分:0)

  

这个灵魂还可以吗?

您的解决方案将无法与async/await一起使用,因为两个不同的线程可以在那里参与,并且[ThreadStatic]属性将不会在异步流中持久保存值。

  

我应该使用AsynLocal还是其他?

我不知道如何使用AsynLocal来实现它。

这是一个基本的想法:

LoggerDll

public static Func<string> UserIpGetter;
public void WriteToLog(string message)
{
    string userIp = UserIpGetter();
    WriteToDB(message, userIp);
}

Asp.Net

//Global.asax
static string GetUserIp()
{
    return System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}
protected void Application_Start(object sender, EventArgs e)
{
     LoggerDll.UserIpGetter = GetUserIp;
}

Asp.Net Core

Startup.cs

public class Startup
{
    static IServiceProvider _serviceProvider;
    static string GetUserIp()
    {
        return _serviceProvider.GetService<IHttpContextAccessor>()
            .HttpContext.Connection.RemoteIpAddress.ToString();
    }
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHttpContextAccessor();
        ...
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        _serviceProvider = app.ApplicationServices;
        LoggerDll.UserIpGetter = GetUserIp;
        ...
    }
}

要改进此代码,您可以声明:interface IUserIpGetter {string GetUserIp();},在Asp.Net中编写一个实现,在Asp.Net Core中编写另一个,在DI中注册并将它们注入LoggerDll.ctor