Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.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
C# 如何实现补丁HTTP?_C#_Asp.net Web Api2_Patch - Fatal编程技术网

C# 如何实现补丁HTTP?

C# 如何实现补丁HTTP?,c#,asp.net-web-api2,patch,C#,Asp.net Web Api2,Patch,我正在用MicrosoftWebAPI2开发一个web服务 我有个人控制器,我会处理补丁HTTP请求。下面是我的个人控制器: namespace MyAssembly.WebApi.Controllers { [RoutePrefix("api/Person")] public class PersonController : BaseController { [HttpGet] public IHttpActionResult GetAl

我正在用MicrosoftWebAPI2开发一个web服务

我有个人控制器,我会处理补丁HTTP请求。下面是我的个人控制器:

namespace MyAssembly.WebApi.Controllers
{
    [RoutePrefix("api/Person")]
    public class PersonController : BaseController
    {
        [HttpGet]
        public IHttpActionResult GetAll(int id)
        {
            // get logic...
        }

        [HttpPost]
        [Route("api/Person/{id:int}")]
        public IHttpActionResult Create(int id, Person dto)
        {
            // post logic...
        }

    [HttpPatch]
    [Route("api/Person/{id:int}")]
    public IHttpActionResult Update(int id, object dto)
    {
        Person currentPerson = myRepo.Get(id);

        currentPerson.patch(dto); // <-- How can I "patch" currentPerson object?

        myRepo.Update(id, currentPerson);

        return Ok();
    }
}
我的目标是用
dto
对象中的所有指定属性更新
currentPerson
对象的所有属性

我的HTTP修补程序请求应如下所示:

PATCH /api/Person/1
Host: localhost
Content-Type: application/json
Cache-Control: no-cache

{
    "Name": "Alessia",
    "PreferredNumbers": [1,2,3],
    "PreferredSerieTV": ["Serie1", "Serie2"]
}
public IHttpActionResult Update(int id, Delta<Person> dto) { ... }
我尝试过使用Delta对象,但整数矩阵存在一个已知问题。我之前的签名如下:

PATCH /api/Person/1
Host: localhost
Content-Type: application/json
Cache-Control: no-cache

{
    "Name": "Alessia",
    "PreferredNumbers": [1,2,3],
    "PreferredSerieTV": ["Serie1", "Serie2"]
}
public IHttpActionResult Update(int id, Delta<Person> dto) { ... }
thown异常的代码行如下所示:

private static void updateObjectPropertyCore<TObject>(TObject target, string propertyName, object value) where TObject : class
{
    var type = typeof(TObject);
    var property = type.GetPropertyCaseInsensitive(propertyName);
    if (property != null && property.CanWrite)
    {
        property.SetValue(target, value); <---
    }
}
private static void updateObjectPropertyCore(TObject目标,字符串propertyName,对象值),其中TObject:class
{
var类型=类型(TObject);
var property=type.getPropertyCaseSensitive(propertyName);
if(property!=null&&property.CanWrite)
{

SetValue(target,value);我对PUT和PATCH请求都做了类似的操作

仅接受属性以更改重构操作以接受
IDictionary
以保存更改的属性以进行更新/修补

[HttpPatch]
[Route("api/Person/{id:int}")]
public IHttpActionResult Update(int id, [FromBody] Dictionary<string, object> dto) { ... }
[HttpPatch]
[路由(“api/Person/{id:int}”)]
公共IHttpActionResult更新(int id,[FromBody]字典dto){…}
然后,可以通过以下扩展方法使用反射来访问匹配的属性

public static void patchObject<TObject>(this TObject target, Dictionary<string, object> values) where TObject : class {
    if (target != null) {
        foreach (var kvp in values) {
            updateObjectPropertyCore<TObject>(target, kvp.Key, kvp.Value);
        }
    }
}

private static void updateObjectPropertyCore<TObject>(TObject target, string propertyName, object value) where TObject : class {
    var type = typeof(TObject);
    var property = type.GetPropertyCaseInsensitive(propertyName);
    if (property != null && property.CanWrite) {
        object coercedValue;
        var destinationType = property.PropertyType;
        try {
            coercedValue = Convert.ChangeType(value, destinationType, CultureInfo.CurrentCulture);
        } catch {
            return destinationType.IsValueType ? null : Activator.CreateInstance(destinationType);
        }
        property.SetValue(target, coercedValue);
    }
}

/// <summary>
/// Gets a property by name, ignoring case and searching all interfaces.
/// </summary>
/// <param name="type">The type to inspect.</param>
/// <param name="propertyName">The property to search for.</param>
/// <returns>The property or null if not found.</returns>
public static PropertyInfo GetPropertyCaseInsensitive(this Type type, string propertyName) {

    var typeList = new List<Type> { type };

    if (type.IsInterface()) {
        typeList.AddRange(type.GetInterfaces());
    }

    var flags = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance;

    return typeList
        .Select(interfaceType => interfaceType.GetProperty(propertyName, flags))
        .FirstOrDefault(property => property != null);
}
publicstaticvoidpatchobject(这个TObject目标,字典值),其中TObject:class{
如果(目标!=null){
foreach(值中的var kvp){
updateObjectPropertyCore(目标,kvp.Key,kvp.Value);
}
}
}
私有静态void updateObjectPropertyCore(ToObject目标,字符串propertyName,对象值),其中ToObject:class{
var类型=类型(TObject);
var property=type.getPropertyCaseSensitive(propertyName);
if(property!=null&&property.CanWrite){
对象强制值;
var destinationType=property.PropertyType;
试一试{
强制值=Convert.ChangeType(值、destinationType、CultureInfo.CurrentCulture);
}抓住{
返回destinationType.IsValueType?null:Activator.CreateInstance(destinationType);
}
SetValue(目标,强制值);
}
}
/// 
///按名称获取属性,忽略大小写并搜索所有接口。
/// 
///要检查的类型。
///要搜索的属性。
///属性,如果未找到,则返回null。
公共静态PropertyInfo GetPropertyCaseSensitive(此类型,字符串propertyName){
var typeList=新列表{type};
if(type.IsInterface()){
typeList.AddRange(type.GetInterfaces());
}
var flags=BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance;
返回类型列表
.Select(interfaceType=>interfaceType.GetProperty(propertyName,标志))
.FirstOrDefault(属性=>属性!=null);
}
因此,现在您可以对要修补的对象调用扩展方法

[HttpPatch]
[Route("api/Person/{id:int}")]
public IHttpActionResult Update(int id, [FromBody] Dictionary<string, object> dto) {
    var currentPerson = myRepo.Get(id);

    if(currentPerson == null)
        return NotFound();

    currentPerson.patchObject(dto); // <-- matching keys in dto will modify target object

    myRepo.Update(id, currentPerson);

    return Ok();
}
[HttpPatch]
[路由(“api/Person/{id:int}”)]
公共IHttpActionResult更新(int id,[FromBody]字典dto){
var currentPerson=myRepo.Get(id);
if(currentPerson==null)
返回NotFound();

patchObject(dto);//我对PUT和PATCH请求都做了类似的操作

仅接受属性以更改重构操作以接受
IDictionary
以保存更改的属性以进行更新/修补

[HttpPatch]
[Route("api/Person/{id:int}")]
public IHttpActionResult Update(int id, [FromBody] Dictionary<string, object> dto) { ... }
[HttpPatch]
[路由(“api/Person/{id:int}”)]
公共IHttpActionResult更新(int id,[FromBody]字典dto){…}
然后,可以通过以下扩展方法使用反射来访问匹配的属性

public static void patchObject<TObject>(this TObject target, Dictionary<string, object> values) where TObject : class {
    if (target != null) {
        foreach (var kvp in values) {
            updateObjectPropertyCore<TObject>(target, kvp.Key, kvp.Value);
        }
    }
}

private static void updateObjectPropertyCore<TObject>(TObject target, string propertyName, object value) where TObject : class {
    var type = typeof(TObject);
    var property = type.GetPropertyCaseInsensitive(propertyName);
    if (property != null && property.CanWrite) {
        object coercedValue;
        var destinationType = property.PropertyType;
        try {
            coercedValue = Convert.ChangeType(value, destinationType, CultureInfo.CurrentCulture);
        } catch {
            return destinationType.IsValueType ? null : Activator.CreateInstance(destinationType);
        }
        property.SetValue(target, coercedValue);
    }
}

/// <summary>
/// Gets a property by name, ignoring case and searching all interfaces.
/// </summary>
/// <param name="type">The type to inspect.</param>
/// <param name="propertyName">The property to search for.</param>
/// <returns>The property or null if not found.</returns>
public static PropertyInfo GetPropertyCaseInsensitive(this Type type, string propertyName) {

    var typeList = new List<Type> { type };

    if (type.IsInterface()) {
        typeList.AddRange(type.GetInterfaces());
    }

    var flags = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance;

    return typeList
        .Select(interfaceType => interfaceType.GetProperty(propertyName, flags))
        .FirstOrDefault(property => property != null);
}
publicstaticvoidpatchobject(这个TObject目标,字典值),其中TObject:class{
如果(目标!=null){
foreach(值中的var kvp){
updateObjectPropertyCore(目标,kvp.Key,kvp.Value);
}
}
}
私有静态void updateObjectPropertyCore(ToObject目标,字符串propertyName,对象值),其中ToObject:class{
var类型=类型(TObject);
var property=type.getPropertyCaseSensitive(propertyName);
if(property!=null&&property.CanWrite){
对象强制值;
var destinationType=property.PropertyType;
试一试{
强制值=Convert.ChangeType(值、destinationType、CultureInfo.CurrentCulture);
}抓住{
返回destinationType.IsValueType?null:Activator.CreateInstance(destinationType);
}
SetValue(目标,强制值);
}
}
/// 
///按名称获取属性,忽略大小写并搜索所有接口。
/// 
///要检查的类型。
///要搜索的属性。
///属性,如果未找到,则返回null。
公共静态PropertyInfo GetPropertyCaseSensitive(此类型,字符串propertyName){
var typeList=新列表{type};
if(type.IsInterface()){
typeList.AddRange(type.GetInterfaces());
}
var flags=BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance;
返回类型列表
.Select(interfaceType=>interfaceType.GetProperty(propertyName,标志))
.FirstOrDefault(属性=>属性!=null);
}
因此,现在您可以对要修补的对象调用扩展方法

[HttpPatch]
[Route("api/Person/{id:int}")]
public IHttpActionResult Update(int id, [FromBody] Dictionary<string, object> dto) {
    var currentPerson = myRepo.Get(id);

    if(currentPerson == null)
        return NotFound();

    currentPerson.patchObject(dto); // <-- matching keys in dto will modify target object

    myRepo.Update(id, currentPerson);

    return Ok();
}
[HttpPatch]
[路由(“api/Person/{id:int}”)]
公共IHttpActionResult更新(int id,[FromBody]字典dto){
var currentPerson=myRepo.Get(id);
if(currentPerson==null)
返回NotFound();

currentPerson.patchObject(dto);//为什么在补丁操作中使用
对象dto
?这不应该是
Parson dto
?嗨,Nkosi,dto对象也可以是Person类型。我看不出如何使用“Person”type可以解决这个问题。你能给我一些提示吗?谢谢
但是整数矩阵有一个已知的问题。我以前的签名如下:
已知的问题是什么?为什么
对象dto
在补丁操作中?不应该是这样吗