.Net OData v4 客户端生成 - IDataErrorInfo

.Net OData v4 Client Generation - IDataErrorInfo

我已经使用 OData 客户端生成器创建了一个 OData v4 客户端。这生成了部分类。我想用 IDataErrorInfo.

扩展这个生成的 类
namespace Client.Model {
    public partial class City : IDataErrorInfo
    {
        public String this[String columnName]
        {
            return "";
        }

        public String Error { get { return ""; } }
    }
}

当我喜欢创建一个新城市并将其发送到服务器时

ODataContainer container = new ODataContainer(new Uri("http://localhost:45666/odata"));
container.AddToCities(city);

我收到一个错误

An exception of type 'Microsoft.OData.Client.DataServiceRequestException' occurred in Microsoft.OData.Client.dll.

The request is invalid. The property "Error" does not exist in Server.Model.City.

WebApi 配置:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
            );

        ODataModelBuilder builder = new ODataConventionModelBuilder();
        builder.EntitySet<City>("Cities");
        builder.EntitySet<Country>("Countries");

        config.MapODataServiceRoute(
            routeName: "ODataRoute",
            routePrefix: "odata",
            model: builder.GetEdmModel());
    }
}

是否有可能阻止请求中包含 错误 属性?

OData 客户端生成的模型是部分 classes。当您实施 IDataErrorInfo 时,它会要求您实施 Error 属性 ,当然服务器端不存在。因为你做了一个操作,例如在实体 City 上序列化 City 对象,如果出现错误 属性 它也会被序列化。

一个解决方案可以避免这种情况,并使客户端模型与 UI 分开。你可以试试这个:

namespace Client.Model {
    public partial class City
    {
        public String this[String columnName]
        {
            return "";
        }
    }
}

使用继承创建 UI 相关模型 classes,与生成的模型分开:

namespace UI.Model {
    public class City : Client.Model.City, IDataErrorInfo
    {
        public String Error { get { return ""; } }
    }
}

确保在 UI 上使用 UI.Model.City 并且在调用 OData 服务进行添加操作时,对 UI.Model.City class 对象执行显式转换以进行转换至 Client.Model.City,错误 属性 将消失:

ODataContainer container = new ODataContainer(new Uri("http://localhost:45666/odata"));
container.AddToCities((Client.Model.City)city);

注意: 这种方法有其自身的缺点,因为它可能会导致您在不同的命名空间下使用相同的 class 名称,因此您通常必须在以下情况下使用完整的命名空间路径使用相同的 class 名称。您可以在 UI 模型上使用不同的 prefix/postfix 和 Class 名称来避免它。例如CityViewModel.

也许OData Client Hook可以满足您的要求。请参阅相关问题( )

我的建议是:

  1. 在同一个命名空间中创建部分 class 'City'(使用与生成的 City class 相同的命名空间)并实现 IdataErrorInfo。
  2. 在服务器模型中添加Error 属性。 public string Error {get; set;}

  3. 如果您使用的是 EF 代码优先方法,请排除模型构建器中的错误 属性,以防止在数据库中创建 'Error' 列。 modelBuilder.Entity<YourModelClass>().Ignore(x =>x.Error);

无需在客户端代码中实现 'City' class 中的错误 属性,因为客户端代码生成器会在生成的代码中生成 Error 属性。

我遇到了同样的问题,我是这样解决的。