1

Web API サービスを作成しました。私がやろうとしているのは、その API 関数、つまり SaveSession(string data) をコード ビハインド ボタン クリックから呼び出し、フォーム コレクション データ全体をパラメーターとして文字列形式で渡すことです。webclient.uploadstring(url,string); を介して API の uri を呼び出すと、Web サービスを呼び出していますが、パラメーターが渡されていません。助けてください。

4

1 に答える 1

3

文字列を受け入れるコントローラー アクション メソッドを使用する代わりに、コントローラーに投稿されたフォーム URL エンコードされたコンテンツを読み取ることができます。

以下の例では、SessionController は、form-url でエンコードされたコンテンツの POST を受け入れる SaveSession() メソッドを公開し、セッション データを KeyValuePair インスタンスのコレクションとして読み取ります。

サンプル クライアントは、キーと値のペアのリストを作成し、HttpClient インスタンスを使用して FormUrlEncodedContent を Web API コントローラー メソッドにポストします。

セッションコントローラーの例:

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;

namespace MvcApplication1.Controllers
{
    public class SessionController : ApiController
    {
        /// <summary>
        /// Saves specified the session data.
        /// </summary>
        /// <returns>
        /// A <see cref="HttpResponseMessage"/> that represents the response to the requested operation.
        /// </returns>
        [HttpPost()]
        public HttpResponseMessage SaveSession()
        {
            // Ensure content is form-url-encoded
            if(!IsFormUrlEncodedContent(this.Request.Content))
            {
                return this.Request.CreateResponse(HttpStatusCode.BadRequest);
            }

            // Read content as a collection of key value pairs
            foreach (var parameter in ReadAsFormUrlEncodedContentAsync(this.Request.Content).Result)
            {
                var key     = parameter.Key;
                var value   = parameter.Value;

                if(!String.IsNullOrEmpty(key))
                {
                    // Do some work to persist session data here
                }
            }

            return this.Request.CreateResponse(HttpStatusCode.OK);
        }

        /// <summary>
        /// Determines whether the specified content is form URL encoded content.
        /// </summary>
        /// <param name="content">
        /// The type that the <see cref="IsFormUrlEncodedContent(HttpContent)"/> method operates on.
        /// </param>
        /// <returns>
        /// <see langword="true"/> if the specified content is form URL encoded content; otherwise, <see langword="false"/>.
        /// </returns>
        public static bool IsFormUrlEncodedContent(HttpContent content)
        {
            if (content == null || content.Headers == null)
            {
                return false;
            }

            return String.Equals(
                content.Headers.ContentType.MediaType, 
                FormUrlEncodedMediaTypeFormatter.DefaultMediaType.MediaType, 
                StringComparison.OrdinalIgnoreCase
            );
        }

        /// <summary>
        /// Write the HTTP content to a collection of name/value pairs as an asynchronous operation.
        /// </summary>
        /// <param name="content">
        /// The type that the <see cref="ReadAsFormUrlEncodedContentAsync(HttpContent)"/> method operates on.
        /// </param>
        /// <returns>The <see cref="Task"/> object representing the asynchronous operation.</returns>
        /// <remarks>
        /// The <see cref="ReadAsFormUrlEncodedContentAsync(HttpContent, CancellationToken)"/> method 
        /// uses the <see cref="Encoding.UTF8"/> format (or the character encoding of the document, if specified) 
        /// to parse the content. URL-encoded characters are decoded and multiple occurrences of the same form 
        /// parameter are listed as a single entry with a comma separating each value.
        /// </remarks>
        public static Task<IEnumerable<KeyValuePair<string, string>>> ReadAsFormUrlEncodedContentAsync(HttpContent content)
        {
            return ReadAsFormUrlEncodedContentAsync(content, CancellationToken.None);
        }

        /// <summary>
        /// Write the HTTP content to a collection of name/value pairs as an asynchronous operation.
        /// </summary>
        /// <param name="content">
        /// The type that the <see cref="ReadAsFormUrlEncodedContentAsync(HttpContent, CancellationToken)"/> method operates on.
        /// </param>
        /// <param name="cancellationToken">
        /// The cancellation token used to propagate notification that the operation should be canceled.
        /// </param>
        /// <returns>The <see cref="Task"/> object representing the asynchronous operation.</returns>
        /// <remarks>
        /// The <see cref="ReadAsFormUrlEncodedContentAsync(HttpContent, CancellationToken)"/> method 
        /// uses the <see cref="Encoding.UTF8"/> format (or the character encoding of the document, if specified) 
        /// to parse the content. URL-encoded characters are decoded and multiple occurrences of the same form 
        /// parameter are listed as a single entry with a comma separating each value.
        /// </remarks>
        public static Task<IEnumerable<KeyValuePair<string, string>>> ReadAsFormUrlEncodedContentAsync(HttpContent content, CancellationToken cancellationToken)
        {
            return Task.Factory.StartNew<IEnumerable<KeyValuePair<string, string>>>(
                (object state) =>
                {
                    var result  = new List<KeyValuePair<string, string>>();

                    var httpContent = state as HttpContent;

                    if (httpContent != null)
                    {
                        var encoding    = Encoding.UTF8;
                        var charSet     = httpContent.Headers.ContentType.CharSet;

                        if (!String.IsNullOrEmpty(charSet))
                        {
                            try
                            {
                                encoding    = Encoding.GetEncoding(charSet);
                            }
                            catch (ArgumentException)
                            {
                                encoding    = Encoding.UTF8;
                            }
                        }

                        NameValueCollection parameters = null;

                        using (var reader = new StreamReader(httpContent.ReadAsStreamAsync().Result, encoding))
                        {
                            parameters = HttpUtility.ParseQueryString(reader.ReadToEnd(), encoding);
                        }

                        if (parameters != null)
                        {
                            foreach(var key in parameters.AllKeys)
                            {
                                result.Add(
                                    new KeyValuePair<string, string>(key, parameters[key])
                                );
                            }
                        }
                    }

                    return result;
                },
                content,
                cancellationToken
            );
        }
    }
}

呼び出し元クライアントの例:

using System;
using System.Collections.Generic;
using System.Net.Http;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            using (var client = new HttpClient())
            {
                // Initialize HTTP client
                client.BaseAddress  = new Uri("http://localhost:26242/api/", UriKind.Absolute);
                client.Timeout      = TimeSpan.FromSeconds(10);

                // Build session data to send
                var values          = new List<KeyValuePair<string, string>>();

                values.Add(new KeyValuePair<string, string>("Item1", "Value1"));
                values.Add(new KeyValuePair<string, string>("Item2", "Value2"));
                values.Add(new KeyValuePair<string, string>("Item3", "Value3"));

                // Send session data via POST using form-url-encoded content
                using (var content = new FormUrlEncodedContent(values))
                {
                    using (var response = client.PostAsync("session", content).Result)
                    {
                        Console.WriteLine(response.StatusCode);
                    }
                }
            }
        }
    }
}

通常、IsFormUrlEncodedContentおよびReadAsFormUrlEncodedContentAsyncメソッドを HttpContent の拡張メソッドとして使用しますが、この例の目的のためにそれらをコントローラーに配置しました。

于 2012-10-18T16:54:04.993 に答える