Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何通过FromBody将DataTable传递给Web API POST方法(C#)_C#_Winforms_Asp.net Web Api_Frombodyattribute - Fatal编程技术网

如何通过FromBody将DataTable传递给Web API POST方法(C#)

如何通过FromBody将DataTable传递给Web API POST方法(C#),c#,winforms,asp.net-web-api,frombodyattribute,C#,Winforms,Asp.net Web Api,Frombodyattribute,我正在从Winforms客户端成功调用Web API应用程序中的POST方法,该客户端为存储过程传递一些参数 不过,如果可能的话,我更愿意通过FromBody功能将存储过程的结果(必须首先在客户机上运行)传递给POST方法 要通过网络发送大量数据,但按照我现在的方式,我必须运行SP两次—首先在客户端Winforms应用程序上运行,然后在Web API服务器应用程序上运行,同时调用此SP有时似乎会导致一些问题 因此,如果可行的话,我想通过“FromBody”发送DataTable,或者,如果更可取

我正在从Winforms客户端成功调用Web API应用程序中的POST方法,该客户端为存储过程传递一些参数

不过,如果可能的话,我更愿意通过FromBody功能将存储过程的结果(必须首先在客户机上运行)传递给POST方法

要通过网络发送大量数据,但按照我现在的方式,我必须运行SP两次—首先在客户端Winforms应用程序上运行,然后在Web API服务器应用程序上运行,同时调用此SP有时似乎会导致一些问题

因此,如果可行的话,我想通过“FromBody”发送DataTable,或者,如果更可取的话,发送xml化或jsonized版本的数据(然后在另一端解压,在调用相应的GET方法时将其转换为html进行检索)

有人有任何代码可以显示吗

我的现有代码只通过参数就可以看到

更新 好的,根据Amit Kumar Ghosh的回答,我将代码更改为:

WebApiConfig.cs 客户 …但仍未到达控制器;具体而言,从未到达“DataTable dt=dtPassedAsJson;”中的断点

事实上,它没有崩溃让我有点惊讶,因为传递的是字符串,但声明的数据类型是“DataTable”

更新2 我还尝试了这个方法,因为我意识到我从客户端传递的不是一个真正的stringized/jsonized数据表,而是一个stringized/jsonized通用列表:

WEB API控制器 …还有这个新类别:

// 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;
    }
}
//改编自上面的DataTableMediaTypeFormatter
公共类GenericProduceUsageListMediaTypeFormatter:BufferedMediaTypeFormatter
{
public GenericProduceUsageListMediaTypeFormatter()
:base()
{
SupportedMediaTypes.Add(新的System.Net.Http.Headers.MediaTypeHeaderValue(“test/dt”);
}
公共重写对象ReadFromStream(类型类型、流readStream、,
HttpContent内容,IFormatterLogger格式记录器,System.Threading.CancellationToken CancellationToken)
{
var data=newstreamreader(readStream).ReadToEnd();
var obj=JsonConvert.DeserializeObject(数据);
返回obj;
}
公共覆盖布尔CanReadType(类型)
{
返回true;
}
公共重写bool CanWriteType(类型)
{
返回true;
}
}
尽管如此,控制器中的主断点行:

List<ProduceUsage> _produceUsageList = stringifiedjsondata;
List\u produceUsageList=stringifiedjsondata;

…未到达。

或数据的jsonized版本(然后在另一端解包)

我最终做到了这一点-

public class ParentController : ApiController
{
    public string Post(DataTable id)
    {
        return "hello world";
    }
}
在配置中

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, System.IO.Stream readStream,
        System.Net.Http.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;
    }
}

header of my request -
User-Agent: Fiddler
Host: localhost:60957
Content-Type : test/dt
Content-Length: 28

我以前做过一次,尽管代码现在已经被取代了,所以我只能从TFS历史记录中获取零碎信息

从我的控制台应用程序中,我将发布数据(是一个数据表,我将其转换为POCO),如下所示

            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.");
                }
            }
在服务器端,我有以下几点。这里的概念主要基于链接文章的部分。我知道您特别关注数据表,但我相信您可能会弄乱示例或将数据提取到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;
    }
//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,-第1部分
// http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api
[发布(“修订”)]
公共IEnumerable修订(MyDataType数据)
{
if(ModelState.IsValid&&data!=null)
{
返回ProcessData(data.year、data.period、data.DataToProcess).AsEnumerable();
}
返回null;
}

客户端实际上是以json的形式传递数据表,然后根据特殊的媒体类型webapi运行时在服务器上将json再次转换为数据表。

参见Hernan Guzman的回答


基本上,您必须将“[FromBody]”添加到服务器上的方法中,然后从客户端传递数据,并将其添加到URL参数之后。

您可以发送序列化的json字符串并反序列化回controller。我认为这个难题的答案是Hernan Guzman在“配置”中发布的内容你是说WebApiConfig.cs?DataTableMediaTypeFormatter类也属于其中?还有“config.Formatters.Add()应该进入注册块吗?这看起来很有希望,但我无法检查您的代码;似乎一个DataTable正在从客户端传递,然后在Web API应用程序中转换为Json。这很好,但与顶部的注释(“或数据的jsonized版本(然后在另一端解压)”不匹配。然后如何从Post方法中访问jsonized数据对我来说仍然是个谜,以及如何调用Post方法(如何打包要发送的数据表)。客户端实际上是以json的形式传递一个数据表,然后根据特殊的媒体类型webapi运行时在服务器上将json再次转换为数据表。在我上面的第一条评论中,您仍然没有回答我的问题,关于代码需要放在哪里。是的。它是webapiconfig.csok,但我看不到在您的cod中发生这种情况e、 例如,json在哪里转换为数据表,以及如何从客户端调用它?顺便说一句,这应该是对我的评论的回复(仅限)。媒体类型格式化程序负责。请检查ReadFromStream方法。
public class ParentController : ApiController
{
    public string Post(DataTable id)
    {
        return "hello world";
    }
}
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, System.IO.Stream readStream,
        System.Net.Http.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;
    }
}

header of my request -
User-Agent: Fiddler
Host: localhost:60957
Content-Type : test/dt
Content-Length: 28
[{"Name":"Amit","Age":"27"}]
            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.");
                }
            }
    // 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;
    }