1

ストアド プロシージャのいくつかのパラメーターを渡す Winforms クライアントから Web API アプリで POST メソッドを正常に呼び出しています。

ただし、可能であれば、ストアド プロシージャ (最初にクライアントで実行する必要があります) の結果を FromBody 機能を介して POST メソッドに渡したいと思います。

ネットワーク経由で送信するのは大量のデータですが、現在私が行っている方法では、SP を 2 回実行する必要があります。最初はクライアントの Winforms アプリで、次に Web API サーバー アプリで、この SP の同時呼び出しです。時々問題を起こすようです。

したがって、可能であれば、「FromBody」を介してDataTableを送信するか、できればデータのXML化またはjson化されたバージョンを送信したいと思います(そして、反対側で解凍し、取得のためにhtmlに変換します)対応する GET メソッドが呼び出されたとき。

これを表示できるコードを持っている人はいますか?

パラメータを渡すだけの既存のコードは、ここで見ることができます。

アップデート

さて、Amit Kumar Ghosh の回答に基づいて、コードを次のように変更しました。

WebApiConfig.cs

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        // Configure Web API to use only bearer token authentication.
        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new    
HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

    // Web API routes
    config.MapHttpAttributeRoutes();

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );


    config.Formatters.Add(new DataTableMediaTypeFormatter());
}

public class DataTableMediaTypeFormatter : BufferedMediaTypeFormatter
{
    public DataTableMediaTypeFormatter()
        : base()
    {
        SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("test/dt"));
    }

    public override object ReadFromStream(Type type, Stream readStream,
        HttpContent content, IFormatterLogger formatterLogger, System.Threading.CancellationToken cancellationToken)
    {
        var data = new StreamReader(readStream).ReadToEnd();
        var obj = JsonConvert.DeserializeObject<DataTable>(data);
        return obj;
    }

    public override bool CanReadType(Type type)
    {
        return true;
    }

    public override bool CanWriteType(Type type)
    {
        return true;
    }
}

コントローラ

[Route("{unit}/{begindate}/{enddate}/{stringifiedjsondata}")]
[HttpPost]
public void Post(string unit, string begindate, string enddate, DataTable stringifiedjsondata)
{
    DataTable dt = stringifiedjsondata;
    . . .

クライアント

private async Task SaveProduceUsageFileOnServer(string beginMonth, string beginYear, string endMonth, string endYear)
{
    string beginRange = String.Format("{0}{1}", beginYear, beginMonth);
    string endRange = String.Format("{0}{1}", endYear, endMonth);
    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri("http://localhost:52194");
    string dataAsJson = JsonConvert.SerializeObject(_rawAndCalcdDataAmalgamatedList, Formatting.Indented);
    String uriToCall = String.Format("/api/produceusage/{0}/{1}/{2}/{3}", _unit, beginRange, endRange, @dataAsJson);
    HttpResponseMessage response = await client.PostAsync(uriToCall, null);
}

...しかし、コントローラーにはまだ到達していません。具体的には、「DataTable dt = dtPassedAsJson;」のブレークポイントです。到達することはありません。

実際、文字列が渡されているのに、そこで宣言されているデータ型が「DataTable」であるため、クラッシュしないことにちょっと驚いています。

更新 2

クライアントから渡すのは実際には文字列化/json化されたDataTableではなく、文字列化/json化された汎用リストであることに気付いた後、これも試しました。

Web API コントローラー

[Route("{unit}/{begindate}/{enddate}/{stringifiedjsondata}")]
[HttpPost]
public void Post(string unit, string begindate, string enddate, List<ProduceUsage> stringifiedjsondata)
{
    List<ProduceUsage> _produceUsageList = stringifiedjsondata;

WebApiConfig.cs

これを Register メソッドに追加しました。

config.Formatters.Add(new GenericProduceUsageListMediaTypeFormatter());

...そしてこの新しいクラス:

// adapted from DataTableMediaTypeFormatter above
public class GenericProduceUsageListMediaTypeFormatter : BufferedMediaTypeFormatter
{
    public GenericProduceUsageListMediaTypeFormatter()
        : base()
    {
        SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("test/dt"));
    }

    public override object ReadFromStream(Type type, Stream readStream,
        HttpContent content, IFormatterLogger formatterLogger, System.Threading.CancellationToken cancellationToken)
    {
        var data = new StreamReader(readStream).ReadToEnd();
        var obj = JsonConvert.DeserializeObject<List<ProduceUsage>>(data);
        return obj;
    }

    public override bool CanReadType(Type type)
    {
        return true;
    }

    public override bool CanWriteType(Type type)
    {
        return true;
    }
}

それでも、コントローラーのメインのブレークポイント行は次のとおりです。

List<ProduceUsage> _produceUsageList = stringifiedjsondata;

...達していません。

4

4 に答える 4

1

私はこれを以前に一度行ったことがありますが、コードは現在置き換えられているため、TFS の履歴から少ししか取得できません。

コンソール アプリから、データ (POCO に変換した DataTable) を次のように投稿します。

            using (HttpClient httpClient = new HttpClient())
            {
                MyDataType data = BogusMethodToPopulateData();

                httpClient.BaseAddress = new Uri(Properties.Settings.Default.MyService);
                httpClient.DefaultRequestHeaders.Accept.Clear();
                httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                HttpResponseMessage response;

                // Add reference to System.Net.Http.Formatting.dll
                response = await httpClient.PostAsJsonAsync("api/revise", data);

                if (response.IsSuccessStatusCode)
                {
                    Console.WriteLine("File generation process completed successfully.");
                }
            }

サーバー側では、次のものがありました。ここでの概念は、主にリンク先の投稿の複合型の送信セクションに基づいています。具体的にはDataTablesを見ていることは知っていますが、例をいじったり、データをPOCOに抽出したりできると確信しています。

    // https://damienbod.wordpress.com/2014/08/22/web-api-2-exploring-parameter-binding/
    // http://www.asp.net/web-api/overview/advanced/sending-html-form-data,-part-1
    // http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api
    [POST("revise")]
    public IEnumerable<Revised_Data> Revise(MyDataType data)
    {
        if (ModelState.IsValid && data != null)
        {
            return ProcessData(data.year, data.period, data.DataToProcess).AsEnumerable();
        }
        return null;
    }
于 2016-01-06T07:41:50.453 に答える
0

ここでHernan Guzman の回答を参照してください。

基本的には、サーバー側のメソッドに「[FromBody]」を追加し、クライアントからデータを渡して、URL パラメーターの後に追加する必要があります。

于 2016-01-21T00:39:55.120 に答える