C# 版本控制WebAPI C-通过模型类对v1和v2的不同响应

C# 版本控制WebAPI C-通过模型类对v1和v2的不同响应,c#,asp.net-web-api,C#,Asp.net Web Api,我目前拥有一套API,并实现了某些API的v2。控制器级别I将URL设置为/v2/。我有一个要求,其中一个API响应是 Http响应 { "prd":"product name" } Product.cs public class ProductInfo { [JsonProperty("prd")] public string ProductName { get; set;} } 在API的版本2中,我想将JsonPropertyprd更改为JsonPropertyproduct

我目前拥有一套API,并实现了某些API的v2。控制器级别I将URL设置为/v2/。我有一个要求,其中一个API响应是

Http响应

{
 "prd":"product name"
}
Product.cs

public class ProductInfo
{
  [JsonProperty("prd")]
  public string ProductName { get; set;}
}

在API的版本2中,我想将JsonPropertyprd更改为JsonPropertyproduct_名称。如何根据API的版本动态更改属性名称并忽略某些属性。我不想复制服务层

您可以在Json.Net中使用自定义来实现这一点。在这里,我创建了一个简单的演示示例。您可以根据API版本控制条件执行它

void Main()
{
    var productInfo = new ProductInfo();
    productInfo.ProductName = "Product Name";

    var jsonResolver = new PropertyRenameSerializerContractResolver();
    jsonResolver.RenameProperty(typeof(ProductInfo), "prd", "product_name");

    var serializerSettings = new JsonSerializerSettings();
    serializerSettings.ContractResolver = jsonResolver;

    var json = JsonConvert.SerializeObject(productInfo, serializerSettings);

    Console.WriteLine(json);
}

public class ProductInfo
{
    [JsonProperty("prd")]
    public string ProductName { get; set; }
}

public class PropertyRenameSerializerContractResolver : DefaultContractResolver
{
    private readonly Dictionary<Type, Dictionary<string, string>> _renames;

    public PropertyRenameSerializerContractResolver()
    {
        _renames = new Dictionary<Type, Dictionary<string, string>>();
    }

    public void RenameProperty(Type type, string propertyName, string newJsonPropertyName)
    {
        if (!_renames.ContainsKey(type))
            _renames[type] = new Dictionary<string, string>();

        _renames[type][propertyName] = newJsonPropertyName;
    }

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);

        if (IsRenamed(property.DeclaringType, property.PropertyName, out var newJsonPropertyName))
            property.PropertyName = newJsonPropertyName;

        return property;
    }

    private bool IsRenamed(Type type, string jsonPropertyName, out string newJsonPropertyName)
    {
        Dictionary<string, string> renames;

        if (!_renames.TryGetValue(type, out renames) || !renames.TryGetValue(jsonPropertyName, out newJsonPropertyName))
        {
            newJsonPropertyName = null;
            return false;
        }

        return true;
    }
}
我在一个与您的场景相匹配的场景中使用了这个。有关更多详细信息,请参阅以下文章


不确定这是一个好的方法,你应该为每个版本的API复制你的类。你应该考虑使用DTOS而不是通过API公开你的域模型。这样,您就可以轻松地将ProductInfo映射到v1/v2端点的DTO。我建议您阅读这一良好实践的原因。您最好复制DTO,而不是在维护方面尝试动态更改属性名称。我更喜欢使用ApiVersion属性,并确保每个版本都有自己的特定契约。调用方应该在URL或标题或查询字符串中指定版本号。这样我们就可以确切地知道应该使用哪个模式。使解决方案更加类型安全。尝试了几种不同的技术,但似乎没有一种能完全起作用,创建了一个回购协议,以查看外部别名是否有助于向下投票,因为我认为这是过分的,并且使OP的代码变得更加复杂。@我谦虚地接受了您的向下投票,但我认为您已经将此视为实现此目的的方法之一。除此之外,你认为所有人都在考虑OP的代码来回答这个问题吗?有时候我们需要一些有用的东西。当然,我认为你的答案是实现这一点的一种方法,这就是你发布它的原因,不是吗?。我想在回答之前,很少有人考虑OPS代码。是的,最终一个人需要一些有用的东西。在本例中,请参阅@Boxiom的注释。@KeyurRamoliya我引用了同一个站点并使用了ContractResolver并成功地重命名了属性。感谢这是一种情况,因为你能做一些事情,你绝对不应该真的去做。
{"product_name":"Product Name"}