RestSharp 将复杂模型发送到 API,可以通过 FromForm 读取
ResrSharp send complex model to API that can be read via FromForm
我在 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");
}
我的模型是这样的:
public class SimpleRequest
{
[Required]
public string UserId { get; set; }
public RequestType? RequestType { get; set; }
public DateTime Timestamp { get; set; }
public bool Test { get; set; }
public ExtraData ExtraData { get; set; }
}
public enum RequestType
{
Simple,
Complex,
}
public class ExtraData
{
public string FirstName { get; set; }
public string LastName { get; set; }
public ulong Id { get; set; }
public DateTime RDate { get; set; }
public uint Nr { get; set; }
}
当我向 Postman 提出请求时,我的模型绑定正确:
现在我尝试使用 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
,我们需要通过form-data
或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 } };
}
}
用例
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);
}
我在 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");
}
我的模型是这样的:
public class SimpleRequest
{
[Required]
public string UserId { get; set; }
public RequestType? RequestType { get; set; }
public DateTime Timestamp { get; set; }
public bool Test { get; set; }
public ExtraData ExtraData { get; set; }
}
public enum RequestType
{
Simple,
Complex,
}
public class ExtraData
{
public string FirstName { get; set; }
public string LastName { get; set; }
public ulong Id { get; set; }
public DateTime RDate { get; set; }
public uint Nr { get; set; }
}
当我向 Postman 提出请求时,我的模型绑定正确:
现在我尝试使用 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
,我们需要通过form-data
或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 } }; } }
用例
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); }