以 C# WebApi Get 请求方式传递实体参数

2024-07-28 18:25:15 浏览数 (1)

在 C# 开发中,Web API 是构建基于 HTTP 协议的服务的重要工具。通常,我们会使用 GET 请求来从服务器获取数据。在大多数情况下,GET 请求传递简单参数(例如字符串或整数)就足够了。但是,有时我们需要传递更复杂的数据,例如一个包含多个字段的实体参数。这种情况下,如何优雅地通过 GET 请求传递实体参数呢?本文将详细探讨这一问题,并提供相应的解决方案。

GET 请求与实体参数

HTTP GET 请求的主要目的是从服务器获取资源。根据 RESTful 风格的 API 设计,GET 请求通常不应包含主体数据(body),而应通过 URL 参数传递数据。然而,URL 参数通常用于传递简单的数据类型,如整数、字符串等,对于复杂的实体参数,处理起来会比较麻烦。我们可以通过将实体参数的各个字段作为 URL 参数来实现这种需求。

具体实现

创建 Web API 项目

首先,我们需要创建一个新的 Web API 项目。假设你已经安装了 Visual Studio,可以按照以下步骤创建一个新的 Web API 项目:

  1. 打开 Visual Studio,选择“创建新项目”。
  2. 选择“ASP.NET Core Web 应用程序”模板,点击“下一步”。
  3. 命名你的项目并选择存储位置,点击“创建”。
  4. 在“创建新 ASP.NET Core Web 应用程序”窗口中,选择“API”模板,点击“创建”。

项目创建完成后,我们将在该项目中添加一个控制器和一个包含实体参数的 GET 请求方法。

定义实体类

首先,我们定义一个简单的实体类 Person,包含姓名、年龄和地址字段。

代码语言:javascript复制
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Address { get; set; }
}
创建控制器

接下来,我们创建一个新的控制器 PersonController,其中包含一个 GET 请求方法,该方法接受 Person 类的各个字段作为 URL 参数。

代码语言:javascript复制
using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class PersonController : ControllerBase
{
    [HttpGet]
    public IActionResult GetPerson([FromQuery] string name, [FromQuery] int age, [FromQuery] string address)
    {
        Person person = new Person
        {
            Name = name,
            Age = age,
            Address = address
        };

        return Ok(person);
    }
}

在上面的代码中,[FromQuery] 特性指示 ASP.NET Core 从 URL 查询字符串中绑定参数值。这种方式适用于参数较少的情况。如果实体类有很多属性,手动将所有属性作为 URL 参数传递会显得繁琐而且容易出错。

改进实现

使用自定义模型绑定

为了解决上述问题,我们可以创建一个自定义模型绑定器,将 URL 查询字符串绑定到一个复杂的对象上。首先,我们创建一个自定义模型绑定器 PersonModelBinder

代码语言:javascript复制
using Microsoft.AspNetCore.Mvc.ModelBinding;
using System;
using System.Threading.Tasks;

public class PersonModelBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
        {
            throw new ArgumentNullException(nameof(bindingContext));
        }

        var name = bindingContext.ValueProvider.GetValue("name").FirstValue;
        var age = bindingContext.ValueProvider.GetValue("age").FirstValue;
        var address = bindingContext.ValueProvider.GetValue("address").FirstValue;

        if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(age) || string.IsNullOrEmpty(address))
        {
            bindingContext.Result = ModelBindingResult.Failed();
            return Task.CompletedTask;
        }

        var person = new Person
        {
            Name = name,
            Age = int.Parse(age),
            Address = address
        };

        bindingContext.Result = ModelBindingResult.Success(person);
        return Task.CompletedTask;
    }
}

然后,我们需要创建一个自定义模型绑定器提供程序 PersonModelBinderProvider

代码语言:javascript复制
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using System;

public class PersonModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (context.Metadata.ModelType == typeof(Person))
        {
            return new BinderTypeModelBinder(typeof(PersonModelBinder));
        }

        return null;
    }
}

最后,我们需要在 Startup.cs 中注册自定义模型绑定器提供程序。

代码语言:javascript复制
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers(options =>
    {
        options.ModelBinderProviders.Insert(0, new PersonModelBinderProvider());
    });
}

现在,我们可以修改 PersonController,让其接受 Person 实体参数。

代码语言:javascript复制
[HttpGet]
public IActionResult GetPerson([ModelBinder(BinderType = typeof(PersonModelBinder))] Person person)
{
    return Ok(person);
}

测试

我们可以通过以下 URL 测试上述实现:

代码语言:javascript复制
https://localhost:5001/api/person?name=John&age=30&address=123 Main St

如果一切正常,响应将会是:

代码语言:javascript复制
{
    "name": "John",
    "age": 30,
    "address": "123 Main St"
}

0 人点赞