.NET Core 3.1-HostingEnvironment不包含MapPath的定义

问题描述

我正在使用.NET Core 3.1,并且尝试通过提供私钥来连接到Google的Indexing API。我看过类似的内容Example of Google Indexing API Batch Request using .NEThttps://hamidmosalla.com/2019/12/07/using-google-indexing-api-with-google-api-client-library-for-net/

这是我的代码

using Google.Apis.Auth.OAuth2;
using Google.Apis.Requests;
using Google.Apis.Services;
using Google.Apis.Indexing.v3;
using Google.Apis.Indexing.v3.Data;
using Microsoft.Extensions.Hosting.Internal;

public static class MyClassDownloader {
    public static GoogleCredential GetGoogleCredential()
    {    
        string path = HostingEnvironment.MapPath("/PrivateKey/myprivatekey.json");
        GoogleCredential credential;
    
        using (var stream = new FileStream(path,FileMode.Open,FileAccess.Read))
        {
            credential = GoogleCredential.FromStream(stream).CreateScoped(new[] { "https://www.googleapis.com/auth/indexing" });
        }
    
        return credential;
    }
}

但是,我在关于MapPath的行上遇到了一个错误

'HostingEnvironment' does not contain a deFinition for 'MapPath'

我尝试研究IHostingEnvironment,之后得知它已弃用IWebHostEnvironment。无论我处于开发还是生产中,如何获取JSON文件的正确物理路径?

解决方法

我将MyClassDownloader更改为非静态,并添加一个以IWebHostEnvironment作为参数的构造函数,该构造函数将保存在MyClassDownloader内的变量中。然后,MyClassDownloader需要在Startup.ConfigureServices()中注册。最后,MyClassDownloader.GetGoogleCredential()的每个地方都被调用(例如在控制器中),MyClassDownloader的实例需要可用。通过将该实例注入using类的(例如,控制器)构造函数中,可以使用该实例。

示例(我没有测试该代码):

// MyClassDownloader.cs
// Make MyClassDownloader non static and add constructor
public class MyClassDownloader 
{
    private readonly IWebHostEnvironment webHostEnvironment;

    public MyClassDownloader(IWebHostEnvironment webHostEnvironment) 
    {
        this.webHostEnvironment = webHostEnvironment;
    }

    // Method not static any more
    public GoogleCredential GetGoogleCredential()
    {    
        // Depending on the hosting OS you might have to use backslash but I'm
        // not sure about that
        string path = System.IO.Path.Combine(
            webHostEnvironment.WebRootPath,"/PrivateKey/myprivatekey.json");

        GoogleCredential credential;
    
        using (var stream = new FileStream(path,FileMode.Open,FileAccess.Read))
        {
            credential = GoogleCredential.FromStream(stream).CreateScoped(new[] { "https://www.googleapis.com/auth/indexing" });
        }
    
        return credential;
    }
}

// Startup.cs
public class Startup 
{
    // ... some code

    public void ConfigureServices(IServiceCollection services)
    {
        // ... some code
        
        // Register newly non static MyClassDownloader so it can be injected
        // into classes that need it.
        services.AddTransient<MyClassDownloader>();

        // ... some more code
    }

    // ... some more code
}

// GoogleCredentialConsumer.cs
// Sample class that needs an instance of GoogleCredential. 
// To obtain the GoogleCredential instance,it needs a MyClassDownloader. 
// Might be a controller or another class
public class GoogleCredentialConsumer 
{
    private readonly MyClassDownloader myClassDownloader;

    public GoogleCredentialConsumer(MyClassDownloader myClassDownloader)
    {
        this.myClassDownloader = myClassDownloader;
    }

    public void MethodThatNeedsGoogleCredential()
    {
        var theGoogleCredential = myClassDownloader.GetGoogleCredential();
        // yay,finally I have it!
    }
}