国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

在 ASP.NET Core Web API 中處理 Patch 請求

這篇具有很好參考價(jià)值的文章主要介紹了在 ASP.NET Core Web API 中處理 Patch 請求。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一、概述

PUTPATCH 方法用于更新現(xiàn)有資源。 它們之間的區(qū)別是,PUT 會替換整個(gè)資源,而 PATCH 僅指定更改。

在 ASP.NET Core Web API 中,由于 C# 是一種靜態(tài)語言(dynamic 在此不表),當(dāng)我們定義了一個(gè)類型用于接收 HTTP Patch 請求參數(shù)的時(shí)候,在 Action 中無法直接從實(shí)例中得知客戶端提供了哪些參數(shù)。

比如定義一個(gè)輸入模型和數(shù)據(jù)庫實(shí)體:

public class PersonInput
{
    public string? Name { get; set; }

    public int? Age { get; set; }

    public string? Gender { get; set; }
}

public class PersonEntity
{
    public string Name { get; set; }

    public int Age { get; set; }

    public string Gender { get; set; }
}

再定義一個(gè)以 FromForm 形式接收參數(shù)的 Action:

[HttpPatch]
[Route("patch")]
public ActionResult Patch([FromForm] PersonInput input)
{
    // 測試代碼暫時(shí)將 AutoMapper 配置放在方法內(nèi)。
    var config = new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<PersonInput, PersonEntity>());
    });
    var mapper = config.CreateMapper();

    // entity 從數(shù)據(jù)庫讀取,這里僅演示。
    var entity = new PersonEntity
    {
        Name = "姓名", // 可能會被改變
        Age = 18, // 可能會被改變
        Gender = "我可能會被改變",
    };

    // 如果客戶端只輸入 Name 字段,entity 的 Age 和 Gender 將不能被正確映射或被置為 null。
    mapper.Map(input, entity);

    return Ok();
}
curl --location --request PATCH 'http://localhost:5094/test/patch' \
--form 'Name="foo"'

如果客戶端只提供了 Name 而沒有其他參數(shù),從 HttpContext.Request.Form.Keys 可以得知這一點(diǎn)。如果不使用 AutoMapper,那么就需要使用丑陋的判斷:

[HttpPatch]
[Route("patch")]
public ActionResult Patch([FromForm] PersonInput input)
{
    var keys = _httpContextAccessor.HttpContext.Request.Form.Keys.Select(m => m.ToLower());
    var entity = new PersonEntity
    {
        Name = "姓名", // 可能會被改變
        Age = 18, // 可能會被改變
        Gender = "我可能會被改變",
    };

    if (keys.Contains("name"))
    {
        // 更新 Name(這里忽略合法性判斷)
        entity.Name = input.Name!;
    }
    if (keys.Contains("age"))
    {
        // 更新 Age(這里忽略合法性判斷)
        entity.Age = input.Age!.Value;
    }
    // ... 其他判斷
    return Ok();
}

本文提供一種方式來簡化這個(gè)步驟。

二、將 Keys 保存在 Input Model 中

定義一個(gè)名為 PatchInput 的類:

public abstract class PatchInput
{
    [BindNever]
    public ICollection<string>? PatchKeys { get; set; }
}

PatchKeys 屬性不由客戶端提供,不參與默認(rèn)綁定。

PersonInput 繼承自 PatchInput:

public class PersonInput : PatchInput
{
    public string? Name { get; set; }

    public int? Age { get; set; }

    public string? Gender { get; set; }
}

三、定義 ModelBinderFactory 和 ModelBinder

public class PatchModelBinder : IModelBinder
{
    private readonly IModelBinder _internalModelBinder;

    public PatchModelBinder(IModelBinder internalModelBinder)
    {
        _internalModelBinder = internalModelBinder;
    }

    public async Task BindModelAsync(ModelBindingContext bindingContext)
    {
        await _internalModelBinder.BindModelAsync(bindingContext);
        if (bindingContext.Model is PatchInput model)
        {
            // 將 Form 中的 Keys 保存在 PatchKeys 中
            model.PatchKeys = bindingContext.HttpContext.Request.Form.Keys;
        }
    }
}
public class PatchModelBinderFactory : IModelBinderFactory
{
    private ModelBinderFactory _modelBinderFactory;

    public PatchModelBinderFactory(
        IModelMetadataProvider metadataProvider,
        IOptions<MvcOptions> options,
        IServiceProvider serviceProvider)
    {
        _modelBinderFactory = new ModelBinderFactory(metadataProvider, options, serviceProvider);
    }

    public IModelBinder CreateBinder(ModelBinderFactoryContext context)
    {
        var modelBinder = _modelBinderFactory.CreateBinder(context);
        // ComplexObjectModelBinder 是 internal 類
        if (typeof(PatchInput).IsAssignableFrom(context.Metadata.ModelType)
            && modelBinder.GetType().ToString().EndsWith("ComplexObjectModelBinder"))
        {
            modelBinder = new PatchModelBinder(modelBinder);
        }
        return modelBinder;
    }
}

四、在 ASP.NET Core 項(xiàng)目中替換 ModelBinderFactory

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddPatchMapper();

AddPatchMapper 是一個(gè)簡單的擴(kuò)展方法:

public static class PatchMapperExtensions
{
    public static IServiceCollection AddPatchMapper(this IServiceCollection services)
    {
        services.Replace(ServiceDescriptor.Singleton<IModelBinderFactory, PatchModelBinderFactory>());
        return services;
    }
}

到目前為止,在 Action 中已經(jīng)能獲取到請求的 Key 了。

[HttpPatch]
[Route("patch")]
public ActionResult Patch([FromForm] PersonInput input)
{
    // 不需要手工給 input.PatchKeys 賦值。
    return Ok();
}

PatchKeys 的作用是利用 AutoMapper。

五、擴(kuò)展 AutoMapper

 public static class AutoMapperExtensions
{
    public static IMappingExpression<TSource, TDestination> CreateMapWithPath<TSource, TDestination>(this IMapperConfigurationExpression cfg)
        where TSource : PatchInput
    {
        return cfg.CreateMap<TSource, TDestination>().ApplyPatchKeysCondition<TSource, TDestination>();
    }

    private static IMappingExpression<TSource, TDestination> ApplyPatchKeysCondition<TSource, TDestination>(
        this IMappingExpression<TSource, TDestination> mappingExpression)
        where TSource : PatchInput
    {
        mappingExpression.ForAllMembers(opts =>
        {
            opts.Condition((src, dest, srcMember, destMember, context) =>
            {
                return src.PatchKeys == null || src.PatchKeys.Contains(opts.DestinationMember.Name.ToLower());
            });
        });
        return mappingExpression;
    }
}

六、模型映射

[HttpPatch]
[Route("patch")]
public ActionResult Patch([FromForm] PersonInput input)
{
    // 1. 目前僅支持 `FromForm`,即 `x-www-form_urlencoded` 和 `form-data`;暫不支持 `FromBody` 如 `raw` 等。
    // 2. 使用 ModelBinderFractory 創(chuàng)建 ModelBinder 而不是 ModelBinderProvider 以便于未來支持更多的輸入格式。
    // 3. 目前還沒有支持多級結(jié)構(gòu)。
    // 4. 測試代碼暫時(shí)將 AutoMapper 配置放在方法內(nèi)。

    var config = new MapperConfiguration(cfg =>
    {
        // 使用 CreateMapWithPath 代替 CreateMap
        cfg.CreateMapWithPath<PersonInput, PersonEntity>();
    });
    var mapper = config.CreateMapper();

    // PersonEntity 有 3 個(gè)屬性,客戶端如果提供的參數(shù)參數(shù)不足 3 個(gè),在 Map 時(shí)未提供參數(shù)的屬性值不會被改變。
    var entity = new PersonEntity
    {
        Name = "姓名",
        Age = 18,
        Gender = "如果客戶端沒有提供本參數(shù),那我的值不會被改變"
    };
    mapper.Map(input, entity);

    return Ok();
}

七、測試

curl --location --request PATCH 'http://localhost:5094/test/patch' \
--form 'Name="foo"'

curl --location --request PATCH 'http://localhost:5094/test/patch' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'Name=foo'

下一步

嘗試 INotifypropertyChangedFodyPropertyChanged 來獲取 Keys。

源碼

Tubumu.PatchMapper

參考資料

GraphQL.NET
如何在 ASP.NET Core Web API 中處理 JSON Patch 請求文章來源地址http://www.zghlxwxcb.cn/news/detail-442476.html

到了這里,關(guān)于在 ASP.NET Core Web API 中處理 Patch 請求的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • ASP.NET Core Web API 流式返回,逐字顯示

    ASP.NET Core Web API 流式返回,逐字顯示

    Websocket、SSE(Server-Sent Events)和長輪詢(Long Polling)都是用于網(wǎng)頁和服務(wù)端通信的技術(shù)。 Websocket是一種全雙工通信協(xié)議,能夠?qū)崿F(xiàn)客戶端和服務(wù)端之間的實(shí)時(shí)通信。它基于TCP協(xié)議,并且允許服務(wù)器主動向客戶端推送數(shù)據(jù),同時(shí)也允許客戶端向服務(wù)器發(fā)送數(shù)據(jù)。 SSE是一種單向

    2023年04月23日
    瀏覽(21)
  • ASP.NET Core Web API入門之三:使用EF Core

    ASP.NET Core Web API入門之三:使用EF Core

    一般來講我們做項(xiàng)目都會用實(shí)體類跟數(shù)據(jù)庫實(shí)體進(jìn)行關(guān)系對應(yīng),這樣的好處方便我們維護(hù)、增刪改查,并且可以減少SQL的編寫,從而統(tǒng)一風(fēng)格,那么 Entity Framework Core 就是很不錯(cuò)的ORM框架。 1、跨數(shù)據(jù)庫支持能力強(qiáng)大,只需修改配置就可以輕松實(shí)現(xiàn)數(shù)據(jù)庫切換。 2、提升了開發(fā)效

    2024年02月10日
    瀏覽(22)
  • Asp.Net Core服務(wù)端處理請求過來的壓縮格式

    ? ? ? ? 之前是直接傳沒有經(jīng)過壓縮的文件字節(jié),有時(shí)文件過大的話,可能占寬帶就多,寬帶流量都是錢。后來有個(gè)想法,在客戶端把文件進(jìn)行壓縮,把壓縮的文件流發(fā)給服務(wù)端進(jìn)行解壓。 1,先修改項(xiàng)目中 Startup.cs 文件中ConfigureServices()方法中的代碼: 2?,先修改項(xiàng)目中 S

    2024年02月06日
    瀏覽(93)
  • 2.1 .net 8 ASP.NET Core Web API - Controller詳解

    2.1 .net 8 ASP.NET Core Web API - Controller詳解

    書接上回,上節(jié)我們留了幾個(gè)問題,即: 1、接口Hello的名字究竟怎么來的? 2、我們?nèi)绻氚呀涌诟某善渌拿Q,應(yīng)該怎么做? 3、我們繼承ControllerBase,以及[Route(“[controller]”)]屬性,又是分別起到什么作用? 需要解決以上幾個(gè)問題,我們就要繼續(xù)深入研究Controller相關(guān)的

    2024年02月20日
    瀏覽(22)
  • ASP.NET Core 中基于 Controller 的 Web API

    ASP.NET Core 中基于 Controller 的 Web API

    客戶端發(fā)送Http請求,Contoller響應(yīng)請求,并從數(shù)據(jù)庫讀取數(shù)據(jù),序列化數(shù)據(jù),然后通過 Http Response返回序列化的數(shù)據(jù)。 Web API 的所有controllers 一般繼承于 ControllerBase 類,而不是Controller 類。 因?yàn)?Controller 類也繼承自ControllerBase 類,但是支持views,而API一般不需要這個(gè)功能。 Co

    2024年02月10日
    瀏覽(29)
  • 【ASP.NET Core 基礎(chǔ)知識】--路由和請求處理--路由概念(二)

    一、路由參數(shù)傳遞方式 1.1 查詢字符串參數(shù) 在路由中,查詢字符串參數(shù)是一種常見的方式傳遞信息。這種方式通過URL中的查詢字符串(?key1=value1key2=value2)將參數(shù)附加到請求中。在ASP.NET Core中,可以通過以下方式在控制器動作方法中接收查詢字符串參數(shù): 在上述例子中,查詢

    2024年01月21日
    瀏覽(377)
  • 【ASP.NET Core 基礎(chǔ)知識】--路由和請求處理--路由概念(一)

    在Web應(yīng)用中,路由是一個(gè)至關(guān)重要的概念,它負(fù)責(zé)將用戶的請求映射到相應(yīng)的處理程序,以確保正確的頁面或資源被呈現(xiàn)給用戶。通過將用戶請求與適當(dāng)?shù)奶幚沓绦蜿P(guān)聯(lián)起來,使得應(yīng)用能夠以有序和可維護(hù)的方式響應(yīng)用戶的操作。 一、ASP.NET Core路由基礎(chǔ) 1.1 路由的定義和作用

    2024年01月19日
    瀏覽(99)
  • ASP.NET Core 中基于 Minimal APIs 的Web API

    Minimal APIs 是ASP.NET Core中快速構(gòu)建 REST API 的方式,可以用最少的代碼構(gòu)建全功能的REST API。比如下面三行代碼: 可以實(shí)現(xiàn)在請求網(wǎng)站根目錄結(jié)點(diǎn)的時(shí)候,返回\\\"Hello World!\\\"。 這種方式的Web API可以用于構(gòu)建微服務(wù),極簡功能的網(wǎng)站。 下面代碼,將幾個(gè) HTTP 請求的 url映射到 Lambda

    2024年02月10日
    瀏覽(25)
  • ASP.NET Core Web API 流式返回,實(shí)現(xiàn)ChatGPT逐字顯示

    ASP.NET Core Web API 流式返回,實(shí)現(xiàn)ChatGPT逐字顯示

    ??作者:科技、互聯(lián)網(wǎng)行業(yè)優(yōu)質(zhì)創(chuàng)作者 ??專注領(lǐng)域:.Net技術(shù)、軟件架構(gòu)、人工智能、數(shù)字化轉(zhuǎn)型、DeveloperSharp、微服務(wù)、工業(yè)互聯(lián)網(wǎng)、智能制造 ??歡迎關(guān)注我(Net數(shù)字智慧化基地),里面有很多 高價(jià)值 技術(shù)文章, 是你刻苦努力也積累不到的經(jīng)驗(yàn) ,能助你快速成長。升職

    2024年02月22日
    瀏覽(26)
  • ASP.NET Core 的 Web Api 實(shí)現(xiàn)限流 中間件

    ASP.NET Core 的 Web Api 實(shí)現(xiàn)限流 中間件

    Microsoft.AspNetCore.RateLimiting ?中間件提供速率限制(限流)中間件。 它是.NET 7 以上版本才支持的中間件,剛看了一下,確實(shí)挺好用,下面給大家簡單介紹一下: RateLimiterOptionsExtensions?類提供下列用于限制速率的擴(kuò)展方法:????? 固定窗口限制器 滑動窗口限制器 令牌桶限

    2024年01月17日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包