C# ResrSharp将复杂模型发送到可以通过FromForm读取的API

C# ResrSharp将复杂模型发送到可以通过FromForm读取的API,c#,.net,asp.net-core,restsharp,C#,.net,Asp.net Core,Restsharp,我在ASP.NET Core 2.2 WebAPI中有一个非常简单的方法: [HttpPut] public async Task<IActionResult> Put([FromForm] SimpleRequest request, [FromForm] string param1) { if (request.ExtraData == null) return BadRequest("Please send data"); await Task.Complete

我在ASP.NET Core 2.2 WebAPI中有一个非常简单的方法:

[HttpPut]
public async Task<IActionResult> Put([FromForm] SimpleRequest request, [FromForm] string param1)
{
    if (request.ExtraData == null) return BadRequest("Please send data");
    await Task.CompletedTask;
    return Ok("Works");
}
当我向邮递员发出请求时,我的模型已正确绑定:

现在,我尝试使用RestSharp创建相同的。当我使用以下代码时,它工作正常:

var client = new RestClient("https://localhost:44325/api/values");
var request = new RestRequest(Method.PUT);

request.AddParameter("UserId", "Sample", ParameterType.GetOrPost);
request.AddParameter("RequestType", "Simple", ParameterType.GetOrPost);
request.AddParameter("Timestamp", DateTime.Now, ParameterType.GetOrPost);
request.AddParameter("Test", true, ParameterType.GetOrPost);
request.AddParameter("ExtraData.FirstName", "John", ParameterType.GetOrPost);
request.AddParameter("ExtraData.LastName", "Smith", ParameterType.GetOrPost);
request.AddParameter("ExtraData.Id", 1234, ParameterType.GetOrPost);
request.AddParameter("ExtraData.Nr", 1, ParameterType.GetOrPost);
request.AddParameter("ExtraData.RDate", DateTime.Now.AddDays(-2), ParameterType.GetOrPost);

request.AddParameter("param1", "YES", ParameterType.GetOrPost);

var response = client.Execute(request);
但是我想重用我的模型,因为它们在单独的DLL中共享

我创建的模型如下所示:

var model = new SimpleRequest
{
    UserId = "Sample",
    RequestType = RequestType.Simple,
    Timestamp = DateTime.Now,
    Test = true,
    ExtraData = new ExtraData
    {
        FirstName = "John",
        LastName = "Smith",
        Id = 1234,
        Nr = 1,
        RDate = DateTime.Now.AddDays(-2)
    }
};
但我无法通过请求传递此模型,以便它可以正确地反序列化到我的对象。 我尝试过使用
request.AddJsonBody
,但失败了

通过RestSharp传递上述模型的正确方法是什么?
我应该如何序列化它(或添加为参数)以使其工作。

对于
FromForm
,我们需要通过
表单数据
x-www-form-urlencoded
发送请求。您可以实现自己的方式将模型转换为
x-www-form-urlencoded
,如:

  • 要转换的扩展方法

    public static class RestSharpExtension
    {
            public static IDictionary<string, string> ToKeyValue(this object metaToken)
            {
            if (metaToken == null)
            {
                    return null;
            }
    
            JToken token = metaToken as JToken;
            if (token == null)
            {
                    return ToKeyValue(JObject.FromObject(metaToken));
            }
    
            if (token.HasValues)
            {
                    var contentData = new Dictionary<string, string>();
                    foreach (var child in token.Children().ToList())
                    {
                    var childContent = child.ToKeyValue();
                    if (childContent != null)
                    {
                            contentData = contentData.Concat(childContent)
                                                    .ToDictionary(k => k.Key, v => v.Value);
                    }
                    }
    
                    return contentData;
            }
    
            var jValue = token as JValue;
            if (jValue?.Value == null)
            {
                    return null;
            }
    
            var value = jValue?.Type == JTokenType.Date ?
                            jValue?.ToString("o", CultureInfo.InvariantCulture) :
                            jValue?.ToString(CultureInfo.InvariantCulture);
    
            return new Dictionary<string, string> { { token.Path, value } };
            }
    }
    
    公共静态类扩展
    {
    公共静态IDictionary ToKeyValue(此对象元令牌)
    {
    if(metaToken==null)
    {
    返回null;
    }
    JToken token=作为JToken的元令牌;
    if(标记==null)
    {
    返回ToKeyValue(JObject.FromObject(metaToken));
    }
    if(token.HasValues)
    {
    var contentData=new Dictionary();
    foreach(token.Children().ToList()中的var child)
    {
    var childContent=child.ToKeyValue();
    if(childContent!=null)
    {
    contentData=contentData.Concat(childContent)
    .ToDictionary(k=>k.Key,v=>v.Value);
    }
    }
    返回内容数据;
    }
    var jValue=标记为jValue;
    if(jValue?.Value==null)
    {
    返回null;
    }
    var value=jValue?.Type==JTokenType.Date?
    jValue?.ToString(“o”,CultureInfo.InvariantCulture):
    jValue?.ToString(CultureInfo.InvariantCulture);
    返回新字典{{token.Path,value}};
    }
    }
    
  • 用例

    public async Task<IActionResult> Index()
    {
        var model = new SimpleRequest
                            {
                                UserId = "Sample",
                                RequestType = RequestType.Simple,
                                Timestamp = DateTime.Now,
                                Test = true,
                                ExtraData = new ExtraData
                                {
                                    FirstName = "John",
                                    LastName = "Smith",
                                    Id = 1234,
                                    Nr = 1,
                                    RDate = DateTime.Now.AddDays(-2)
                                }
                            };
        var keyValueContent = model.ToKeyValue();
        keyValueContent.Add("param1", "YES");
        var formUrlEncodedContent = new FormUrlEncodedContent(keyValueContent);
        var urlEncodedString = await formUrlEncodedContent.ReadAsStringAsync();
    
        var client = new RestClient("http://localhost:51420/api/values/Put");
        var request = new RestRequest(Method.PUT);
    
        request.AddParameter("application/x-www-form-urlencoded", urlEncodedString, ParameterType.RequestBody);
    
        var response = client.Execute(request);
    }
    
    公共异步任务索引()
    {
    var模型=新的SimpleRequest
    {
    UserId=“Sample”,
    RequestType=RequestType.Simple,
    时间戳=日期时间。现在,
    测试=真,
    ExtraData=新的ExtraData
    {
    FirstName=“约翰”,
    LastName=“史密斯”,
    Id=1234,
    Nr=1,
    RDate=DateTime.Now.AddDays(-2)
    }
    };
    var keyValueContent=model.ToKeyValue();
    添加(“参数1”、“是”);
    var formUrlEncodedContent=新formUrlEncodedContent(keyValueContent);
    var urlEncodedString=wait formUrlEncodedContent.ReadAsStringAsync();
    var client=新的RestClient(“http://localhost:51420/api/values/Put");
    var请求=新的重新请求(Method.PUT);
    request.AddParameter(“application/x-www-form-urlencoded”,urlEncodedString,ParameterType.RequestBody);
    var response=client.Execute(请求);
    }
    

  • 您还需要共享有问题的代码。您所说的
    失败是什么意思?你有什么错误吗?不要使用
    FromForm
    尝试使用
    FromBody
    @ChetanRanpariya by fails,我的意思是我在Put方法中得到空的
    request
    param1
    。问题是我无法更改此属性。上面的代码只是为了说明我的问题,真正的代码更复杂,并且已经部署好了。我需要为已经在工作的API创建一个客户端。API希望有效负载以
    形式
    属性而不是作为请求主体发送。因此,您不能将负载作为JSON请求主体发送。您只需要通过查询字符串发送所有数据。如果希望能够将负载作为JSON主体发送,则API需要更改其行为。和不是您问题的答案,但它们将帮助您理解API客户端在这里做不了什么。@ChetanRanpariya所以我的问题应该是如何将我的模型“转换”为FormData(查询字符串)这是否可能(内置)通过RestSharp?工作得很好。非常感谢。这应该是内置的功能。我认为我的用例是有效的,我不仅想重用模型。
    public async Task<IActionResult> Index()
    {
        var model = new SimpleRequest
                            {
                                UserId = "Sample",
                                RequestType = RequestType.Simple,
                                Timestamp = DateTime.Now,
                                Test = true,
                                ExtraData = new ExtraData
                                {
                                    FirstName = "John",
                                    LastName = "Smith",
                                    Id = 1234,
                                    Nr = 1,
                                    RDate = DateTime.Now.AddDays(-2)
                                }
                            };
        var keyValueContent = model.ToKeyValue();
        keyValueContent.Add("param1", "YES");
        var formUrlEncodedContent = new FormUrlEncodedContent(keyValueContent);
        var urlEncodedString = await formUrlEncodedContent.ReadAsStringAsync();
    
        var client = new RestClient("http://localhost:51420/api/values/Put");
        var request = new RestRequest(Method.PUT);
    
        request.AddParameter("application/x-www-form-urlencoded", urlEncodedString, ParameterType.RequestBody);
    
        var response = client.Execute(request);
    }