Skip to main content
 首页 » 编程设计

c#之Azure Function C#之Http 触发器抛出 System.Web.Extensions 找不到

2024年02月04日30mate10pro

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

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 runtime不同造成的。

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

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

要在 ~2 运行时实现这一点,请在 ~2 中创建一个 httptrigger 并将示例代码替换为下面的代码片段。请注意,您还必须在应用程序设置中添加 PBIE_TENANT_ID,其值来自 Azure Active Directory> Properties>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; } 
}