Функция Azure C # - Http Trigger выдает System.Web.Extensions не может быть найдено - PullRequest
0 голосов
/ 12 октября 2018

Я пытаюсь создать функцию, запускаемую по протоколу C # HTTP, на портале Azure (Embedded Analytics с Power BI).Я следую посту Тайгана (https://www.taygan.co/blog/2018/05/14/embedded-analytics-with-power-bi) и использую ссылку для System.Web.Extensions, но она выдает:

Файл метаданных 'System.Web.Extensions' не найден

Это код:

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

Как это исправить?Пожалуйста, помогите мне, спасибо.

1 Ответ

0 голосов
/ 12 октября 2018

Проблема вызвана разницей времени выполнения функции.

Учебное пособие, которое вы выполняете, создает функцию в ~ 1 среде выполнения, где код нацелен на .NET Framework, а созданная вами - в среде выполнения ~ 2, которая работает на.NET Core env.Когда мы создаем новое приложение-функцию, его время выполнения по умолчанию устанавливается на ~ 2.

Решение состоит в том, чтобы установить FUNCTIONS_EXTENSION_VERSION на ~1 в настройках приложения на портале.

Для этогово время выполнения ~ 2 создайте httptrigger в ~ 2 и замените образец кода фрагментом ниже.Обратите внимание, что вы также должны добавить PBIE_TENANT_ID в настройках приложения со значением get из Azure Active Directory> Свойства> Идентификатор каталога.

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