简体   繁体   English

Azure函数C#-找不到Http触发器引发System.Web.Extensions

[英]Azure Function C# - Http Trigger throws System.Web.Extensions could not be found

I am trying to create a C# HTTP-triggered Function from the Azure portal (Embedded Analytics with Power BI). 我正在尝试从Azure门户(带有Power BI的嵌入式分析)创建C#HTTP触发的函数。 I follow the post of Taygan ( https://www.taygan.co/blog/2018/05/14/embedded-analytics-with-power-bi ) and using the ref for System.Web.Extensions but it throw: 我遵循Taygan的帖子( https://www.taygan.co/blog/2018/05/14/embedded-analytics-with-power-bi )并将ref用于System.Web.Extensions,但它抛出:

Metadata file 'System.Web.Extensions' could not be found 找不到元数据文件“ System.Web.Extensions”

This is the code: 这是代码:

#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; }
}

How can I fix it? 我该如何解决? Please help me, thank you. 请帮助我,谢谢。

Problem is caused by the difference of Function runtime. 问题是由功能运行时间的差异引起的。

The tutorial you follow creates function on ~1 runtime where code targets at .NET Framework , while the one you create is on ~2 runtime which runs on .NET Core env. 您遵循的教程将在〜1运行时上创建函数,其中代码以.NET Framework为目标,而您所创建的教程则在〜2运行时上运行,该运行在.NET Core env上。 When we create a new Function app its runtime is set to ~2 by default now. 现在,当我们创建一个新的Function应用时,其运行时默认设置为〜2。

Solution is to set FUNCTIONS_EXTENSION_VERSION to ~1 in Application settings on portal. 解决方案是在门户网站的“应用程序设置”中将FUNCTIONS_EXTENSION_VERSION设置为~1

To achieve that in ~2 runtime, create a httptrigger in ~2 and replace the sample code with snippet below. 要在〜2运行时中实现此目的,请在〜2中创建一个httptrigger,并将示例代码替换为下面的代码段。 Note you also have to add PBIE_TENANT_ID in Application settings with value get from Azure Active Directory> Properties>Directory ID. 请注意,您还必须在“应用程序设置”中添加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; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM