c# - Azure Function C# - Http 触发器抛出 System.Web.Extensions 无法找到

标签 c# azure powerbi azure-functions

我正在尝试从 Azure 门户(使用 Power BI 的嵌入式分析)创建 C# HTTP 触发函数。我关注 Taygan ( https://www.taygan.co/blog/2018/05/14/embedded-analytics-with-power-bi ) 的帖子并使用 System.Web.Extensions 的引用,但它抛出:

Metadata file 'System.Web.Extensions' could not be found

这是代码:

#r "System.Web.Extensions"
using System.Configuration;
using System.Net;
using System.Text;
using System.Web.Script.Serialization;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Microsoft.PowerBI.Api.V2;
using Microsoft.PowerBI.Api.V2.Models;
using Microsoft.Rest;

// Static Values
static string authorityUrl = "https://login.windows.net/common/oauth2/authorize/";
static string resourceUrl = "https://analysis.windows.net/powerbi/api";
static string apiUrl = "https://api.powerbi.com/";
static string clientId = ConfigurationManager.AppSettings["PBIE_CLIENT_ID"];
static string username = ConfigurationManager.AppSettings["PBIE_USERNAME"];
static string password = ConfigurationManager.AppSettings["PBIE_PASSWORD"];
static string groupId = ConfigurationManager.AppSettings["PBIE_GROUP_ID"];
static string reportId = ConfigurationManager.AppSettings["PBIE_REPORT_ID"];

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{

    // Authenticate with Azure Ad > Get Access Token > Get Token Credentials
    var credential = new UserPasswordCredential(username, password);
    var authenticationContext = new AuthenticationContext(authorityUrl);
    var authenticationResult = await authenticationContext.AcquireTokenAsync(resourceUrl, clientId, credential);
    string accessToken = authenticationResult.AccessToken;
    var tokenCredentials = new TokenCredentials(accessToken, "Bearer");

    using (var client = new PowerBIClient(new Uri(apiUrl), tokenCredentials))
    {
        // Embed URL
        Report report = client.Reports.GetReportInGroup(groupId, reportId);
        string embedUrl = report.EmbedUrl;

        // Embed Token
        var generateTokenRequestParameters = new GenerateTokenRequest(accessLevel: "view");
        EmbedToken embedToken = client.Reports.GenerateTokenInGroup(groupId, reportId, generateTokenRequestParameters);

        // JSON Response
        EmbedContent data = new EmbedContent();
        data.EmbedToken = embedToken.Token;
        data.EmbedUrl = embedUrl;
        data.ReportId = reportId;
        JavaScriptSerializer js = new JavaScriptSerializer();
        string jsonp = "callback(" +  js.Serialize(data) + ");";

        // Return Response
        return new HttpResponseMessage(HttpStatusCode.OK) 
        {
            Content = new StringContent(jsonp, Encoding.UTF8, "application/json")
        };
    }
}

public class EmbedContent
{
    public string EmbedToken { get; set; }
    public string EmbedUrl { get; set; }
    public string ReportId { get; set; }
}

我该如何解决这个问题?请帮助我,谢谢。

最佳答案

问题是由于Function运行时的差异引起的。

您遵循的教程在 ~1 运行时创建函数,其中代码以 .NET Framework 为目标,而您创建的函数则在 ~2 运行时(在 .NET Core env 上运行)上创建。当我们创建一个新的 Function 应用程序时,它的运行时间现在默认设置为 ~2。

解决方案是在门户上的应用程序设置中将 FUNCTIONS_EXTENSION_VERSION 设置为 ~1

要在 ~2 运行时中实现这一目标,请在 ~2 中创建一个 httptrigger 并将示例代码替换为下面的代码片段。请注意,您还必须在应用程序设置中添加 PBIE_TENANT_ID,其值可从 Azure Active Directory> 属性>目录 ID 获取。

#r "Newtonsoft.Json"

using System.Net;
using System.Text;
using Newtonsoft.Json;

static string resourceUrl = "https://analysis.windows.net/powerbi/api";
static string clientId = Environment.GetEnvironmentVariable("PBIE_CLIENT_ID");
static string username = Environment.GetEnvironmentVariable("PBIE_USERNAME");
static string password = Environment.GetEnvironmentVariable("PBIE_PASSWORD");
static string groupId = Environment.GetEnvironmentVariable("PBIE_GROUP_ID");
static string reportId = Environment.GetEnvironmentVariable("PBIE_REPORT_ID");
static string tenantId = Environment.GetEnvironmentVariable("PBIE_TENANT_ID");
static string tokenEndpoint = $"https://login.microsoftonline.com/{tenantId}/oauth2/token";

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, ILogger log)
{
    // Get access token 
    HttpClient authclient = new HttpClient();

    log.LogInformation(resourceUrl);
    log.LogInformation(tokenEndpoint);

    var authContent = new FormUrlEncodedContent(new[]
    {
        new KeyValuePair<string, string>("grant_type", "password"),
        new KeyValuePair<string, string>("username", username),
        new KeyValuePair<string, string>("password", password),
        new KeyValuePair<string, string>("client_id", clientId),
        new KeyValuePair<string, string>("resource", resourceUrl)
    });

    var accessToken = await authclient.PostAsync(tokenEndpoint, authContent).ContinueWith<string>((response) =>
    {
        log.LogInformation(response.Result.StatusCode.ToString());
        log.LogInformation(response.Result.ReasonPhrase.ToString());
        log.LogInformation(response.Result.Content.ReadAsStringAsync().Result);
        AzureAdTokenResponse tokenRes =
            JsonConvert.DeserializeObject<AzureAdTokenResponse>(response.Result.Content.ReadAsStringAsync().Result);
        return tokenRes?.AccessToken;
    });

    // Get PowerBi report url and embed token
    HttpClient powerBiClient = new HttpClient();
    powerBiClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");

    log.LogInformation(accessToken);

    var embedUrl =
        await powerBiClient.GetAsync($"https://api.powerbi.com/v1.0/myorg/groups/{groupId}/reports/{reportId}")
        .ContinueWith<string>((response) =>
        {
            log.LogInformation(response.Result.StatusCode.ToString());
            log.LogInformation(response.Result.ReasonPhrase.ToString());
            PowerBiReport report =
                JsonConvert.DeserializeObject<PowerBiReport>(response.Result.Content.ReadAsStringAsync().Result);
            return report?.EmbedUrl;
        });

    var tokenContent = new FormUrlEncodedContent(new[]
    {
        new KeyValuePair<string, string>("accessLevel", "view")
    });

    var embedToken = await powerBiClient.PostAsync($"https://api.powerbi.com/v1.0/myorg/groups/{groupId}/reports/{reportId}/GenerateToken", tokenContent)
        .ContinueWith<string>((response) =>
        {
            log.LogInformation(response.Result.StatusCode.ToString());
            log.LogInformation(response.Result.ReasonPhrase.ToString());
            PowerBiEmbedToken powerBiEmbedToken =
                JsonConvert.DeserializeObject<PowerBiEmbedToken>(response.Result.Content.ReadAsStringAsync().Result);
            return powerBiEmbedToken?.Token;
        });


    // JSON Response
    EmbedContent data = new EmbedContent
    {
        EmbedToken = embedToken,
        EmbedUrl = embedUrl,
        ReportId = reportId
    };
    string jsonp = "callback(" + JsonConvert.SerializeObject(data) + ");";

    // Return Response
    return new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new StringContent(jsonp, Encoding.UTF8, "application/json")
    };

}

public class AzureAdTokenResponse
{
    [JsonProperty("access_token")]
    public string AccessToken { get; set; }
}

public class PowerBiReport
{
    [JsonProperty(PropertyName = "id")]
    public string Id { get; set; }

    [JsonProperty(PropertyName = "name")]
    public string Name { get; set; }

    [JsonProperty(PropertyName = "webUrl")]
    public string WebUrl { get; set; }

    [JsonProperty(PropertyName = "embedUrl")]
    public string EmbedUrl { get; set; }

    [JsonProperty(PropertyName = "datasetId")]
    public string DatasetId { get; set; }
}

public class PowerBiEmbedToken
{
    [JsonProperty(PropertyName = "token")]
    public string Token { get; set; }

    [JsonProperty(PropertyName = "tokenId")]
    public string TokenId { get; set; }

    [JsonProperty(PropertyName = "expiration")]
    public DateTime? Expiration { get; set; }
}

public class EmbedContent
{
    public string EmbedToken { get; set; }
    public string EmbedUrl { get; set; }
    public string ReportId { get; set; }
}

关于c# - Azure Function C# - Http 触发器抛出 System.Web.Extensions 无法找到,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52772314/

相关文章:

c# - 有没有办法在不使用 JsonIgnore 属性的情况下忽略 Json.NET 中的 get-only 属性?

azure - Microsoft.WindowsAzure.Storage (WindowsAzure.Storage) 9.1.1 在其依赖性之外调用 Newtonsoft 时失败

azure - 无法访问部署在 AKS 上的应用程序

sql - 如何将具有相同 ID 的行合并到一个列表中

C# 将列表项复制到对象数组

c# - 检测用户空闲(每个应用程序实例)

c# - 通过 Emit(Opcodes.Call, methodinfo) 创建一个类型的实例

azure - Azure Linux VM 上的自定义端口连接被拒绝

powerbi - 为什么我的 Power BI 卡视觉对象具有无法删除的视觉级别筛选器?

Angular5 PowerBI 嵌入不工作