基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 2初始设置链接到WAMS

在文章基于Windows Azure Media Service REST API 进行Windows Store/Windows Phone 应用开发系列-Part 1 简介中介绍了基于Windows Azure Media Service(Windows Azure 媒体服务,简称WAMS)进行应用开发的相关信息及包含的基本流程,本文将对如何使用REST API进行WAMS的链接进行详细讲解。

WAMS接受基于 OData 的 HTTP 请求并能够以详细 JSON 或 atom+pub 做出响应。由于WAMS遵循 Azure 设计准则,因此在连接到 WAMS时,每个客户端必须使用一组必需的 HTTP 标头。根据文档媒体服务 REST API 开发的设置可知,每次调用WAMS时,客户端必须在请求中包括一组必需标头,媒体服务支持的标准 HTTP 请求必须的标头列表如下:

Header

Type

Value

Authorization

Bearer

Bearer 是唯一接受的授权机制。

该值还必须包括由 ACS 提供的访问令牌。

x-ms-version

Decimal

2.7

DataServiceVersion

Decimal

3.0

MaxDataServiceVersion

Decimal

3.0

 

若要直接通过 REST API 访问 WAMS,必须从 ACS 检索一个访问令牌,并在向WAMS提出每个 HTTP 请求期间使用该令牌; WAMS 的根 URI 为https://media.windows.net/,先连接到此 URI,如果在响应中收到“301 重定向”,则应随后调用新的 URI。所以访问 WAMS时需要两项内容:由 Azure 访问控制服务 (ACS) 提供的访问令牌(access token)和 WAMS自身的 URI。在创建这些请求时,可以使用任何方法,前提是在调用 WAMS时指定了正确的标头(Header)值,并且传入了正确的访问令牌。

使用 Media Services REST API 连接到 Media Services的常见流程是:

  1.  获取访问令牌;
  2. 连接到WAMS的 URI-https://media.windows.net: 成功连接到该URI后,将收到一个 301 重定向响应,指定另一个WAMS 的URI。开发者必须对这个新 URI 进行后续调用。还可能会收到包含 ODATA API 元数据说明的 HTTP/1.1 200 响应;
  3. 将后续API调用发布到新的URL。

首先来看获取访问令牌的过程,HTTP请求的header及body内容:

POST https://wamsprodglobal001acs.accesscontrol.windows.net/v2/OAuth2-13 HTTP/1.1

Content-Type: application/x-www-form-urlencoded

Host: wamsprodglobal001acs.accesscontrol.windows.net

Content-Length: 120

Expect: 100-continue

Connection: Keep-Alive

          grant_type=client_credentials&client_id=client id value&client_secret=URL-encoded client secret value&scope=urn%3aWindowsAzureMediaServices

      其中client_id和client_secret对应媒体服务的账户名称和编码后的密钥。

为便于解析响应的JSON和HTML 内容,Nuget 添加工具Json.Net 和HtmlAgilityPack

    

 

由于HttpWebRequest 部分函数在WinRT下已被弃用,导致在WinRT下无法对一些header值进行修改如Content-Length,我们在此使用包含丰富的异步支持的HttpClient类。

先定义一些常用变量及函数(CreateBasicAuthenticationHeader):

static string accountName = "MediaServiceAccountName";

static string accountKey = "MediaServiceAccountKey";

private const string acsEndpoint = "https://wamsprodglobal001acs.accesscontrol.windows.net/v2/OAuth2-13";

private const string acsRequestBodyFormat = "grant_type=client_credentials&client_id={0}&client_secret={1}&scope=urn%3aWindowsAzureMediaServices"; 

private string WAMSEndpoint = "https://media.windows.net/";

 

 private static AuthenticationHeaderValue CreateBasicAuthenticationHeader(string acsToken)

        {

            return new AuthenticationHeaderValue("Bearer", acsToken);

        }

 

获取access token的执行过程可参考如下代码:

    private async Task<string> GetAccessTokenAsync(string accountName, string accountKey)

        {           

            HttpClient httpClient = new HttpClient();

            httpClient.MaxResponseContentBufferSize = int.MaxValue;        

            string requestBody = string.Format(CultureInfo.InvariantCulture, acsRequestBodyFormat, accountName, WebUtility.UrlEncode(accountKey));        

            HttpContent body = new StringContent(requestBody);

            body.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");

            var response =await httpClient.PostAsync(acsEndpoint, body);

             if (response.IsSuccessStatusCode)

             {

                 var content = await response.Content.ReadAsStringAsync();            

                 JObject jsonObject = JObject.Parse(content);

                 string acsToken = jsonObject.Value<string>("access_token"); 

                 return acsToken;

             }

             else

             {

                 return null;

             }           

        }

执行成功后,获得ACS token如下:

     

获得ACS token后,再链接到媒体服务的原始URI https://media.windows.net/获取重定向响应以提取新的媒体服务URI, 抓取Fiddler trace可以看到在客户端链接到https://media.windows.net/后,会返回一个301响应,包含了新的媒体服务URI如下,需用从响应内容中解析出该URI,可以使用工具HtmlAgilityPack。获取到新的媒体服务 URI如:https://wamshknclus001rest-hs.cloudapp.net/api/。

 <html>

  <head><title>Object moved</title></head>

  <body>

       <h2>Object moved to <a href="**https://wamshknclus001rest-hs.cloudapp.net/api**/"\>here\</a>.</h2>

   </body>

</html>

     

 

 private async Task<string> ConnectMediaServiceAsync(string acsToken)

        {           

            AuthenticationHeaderValue header = CreateBasicAuthenticationHeader(acsToken);         

            var handler = new HttpClientHandler()

            {

                AllowAutoRedirect = false

            };

            HttpClient httpClient = new HttpClient(handler);

            httpClient.MaxResponseContentBufferSize = int.MaxValue;

            httpClient.DefaultRequestHeaders.Add("Authorization", header.ToString());

            httpClient.DefaultRequestHeaders.Add("x-ms-version", "2.7");

            httpClient.DefaultRequestHeaders.Add("DataServiceVersion", "3.0");

            httpClient.DefaultRequestHeaders.Add("MaxDataServiceVersion", "3.0");

 

           HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, WAMSEndpoint);

           request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

 

            var response = await httpClient.SendAsync(request);

          

            //after connecting to https://media.windows.net, you will receive a 301 redirect specifying another Media Services URI.

            // You must make subsequent calls to the new URI. 

            string wamsEndPointFinal = WAMSEndpoint;

            if (response.StatusCode == HttpStatusCode.Moved || response.StatusCode == HttpStatusCode.MovedPermanently)

            {

                var htmlcontent = await response.Content.ReadAsStringAsync();

                HtmlDocument htmlDocument = new HtmlDocument();

                htmlDocument.LoadHtml(htmlcontent);

                var inputs_a = htmlDocument.DocumentNode.Descendants("a"); 

                string newLocation = null;

                foreach (var input in inputs_a)

                {

                    newLocation = input.Attributes["href"].Value;                  

                }

               

                if (newLocation!=null)

                {

                    wamsEndPointFinal = newLocation;                  

                }    

            }

            return wamsEndPointFinal;

        }

 

完成以上设置,便可以进行后续媒体的上载,将在后续文章中详细讲述,敬请期待。