gpt4 book ai didi

c# - WebApi OData v3 OperationDescriptor 根据格式(atom vs json)返回不同的标题/目标 URI

转载 作者:行者123 更新时间:2023-11-30 12:26:17 24 4
gpt4 key购买 nike

考虑以下带有 OData v3 的简单 ASP.NET Web Api。

MyEntity.cs

public class MyEntity
{
public Guid Id { get; set; }
public string Name { get; set; }
}

MyEntitiesController.cs

public class MyEntitiesController : ODataController
{
public IEnumerable<MyEntity> Get()
{
return new MyEntity[] { new MyEntity() { Id = Guid.NewGuid(), Name = "Name" } };
}

[HttpPost]
public string MyAction()
{
return "Hello World!";
}
}

WebApiConfig.cs

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.Namespace = "MyNamespace";
modelBuilder.ContainerName = "MyContainer";
modelBuilder.EntitySet<MyEntity>("MyEntities");

var action = modelBuilder.Entity<MyEntity>().Action("MyAction");
action.Returns<string>();

foreach (var structuralType in modelBuilder.StructuralTypes)
{
// Resets the namespace so that the service contains only 1 namespace.
structuralType.GetType().GetProperty("Namespace").SetValue(structuralType, "MyNamespace");
}

var model = modelBuilder.GetEdmModel();
config.Routes.MapODataServiceRoute("OData", "odata", model);
}
}

在客户端,我添加了一个简单的服务引用。

程序.cs

class Program
{
static void Main(string[] args)
{
var contextAtom = new MyContainer(new Uri("http://localhost:63939/odata/"));
contextAtom.Format.UseAtom();
var myEntityAtom = contextAtom.MyEntities.First();

// Outputs: http://localhost:63939/odata/MyEntities(guid'2c2431cd-4afa-422b-805b-8398b9a29fec')/MyAction
var uriAtom = contextAtom.GetEntityDescriptor(myEntityAtom).OperationDescriptors.First().Target;
Console.WriteLine(uriAtom);

// Works fine using ATOM format!
var responseAtom = contextAtom.Execute<string>(uriAtom, "POST", true);

var contextJson = new MyContainer(new Uri("http://localhost:63939/odata/"));
contextJson.Format.UseJson();
var myEntityJson = contextJson.MyEntities.First();

// Outputs: http://localhost:63939/odata/MyEntities(guid'f31a8332-025b-4dc9-9bd1-27437ae7966a')/MyContainer.MyAction
var uriJson = contextJson.GetEntityDescriptor(myEntityJson).OperationDescriptors.First().Target;
Console.WriteLine(uriJson);

// Throws an exception using the JSON uri in JSON format!
var responseJson = contextJson.Execute<string>(uriJson, "POST", true);

// Works fine using ATOM uri in JSON format!
var responseJson2 = contextJson.Execute<string>(uriAtom, "POST", true);
}
}

我的问题是,根据用于查询实体的格式,操作描述符目标 URI 是不同的。来自 ATOM 的目标 URI 工作正常,但来自 JSON 的目标 URI 总是抛出异常。

有没有办法让操作描述符在使用两种格式(ATOM 和 JSON)时正常工作,而不是手动连接 URI?

请注意,我在使用 OData v4 时遇到了同样的问题,但将 MyNamespace.MyAction 作为标题和目标 URI 而不是 MyContainer.MyAction。

最佳答案

我能够重现这个问题,这是客户端的一个错误。我发现的唯一解决方法是扩展 MyContainer 类以提供调用操作的强类型方法:

namespace <NAMESPACE_OF_MYCONTAINER_CLASS>
{
public partial class MyContainer
{
public double MyAction(Guid id)
{
Uri actionUri = new Uri(this.BaseUri,
String.Format("MyEntities(guid'{0}')/MyAction", id)
);

return this.Execute<string>(actionUri,
"POST", true).First();
}
}
}

描述here .我已经跟踪了这个问题并且看起来很旧,我发现了这个 post一个人 (Uffe Lauesen) 在他的第二篇文章中解释了当使用 json 格式时他读取 ActionDescriptor 类的 Title(而不是 Target)属性时的一些异常行为。

您仍然在他们的 github page. 中打开了 odata.net 的问题

更新:

我跟踪了这​​个问题,Atom 格式使用 NoOpEntityMetadataBuilder 返回非计算操作(使用 atom 格式它解析 xml 并从提要中获取操作)。

internal override IEnumerable<ODataAction> GetActions()
{
DebugUtils.CheckNoExternalCallers();
return this.entry.NonComputedActions;
}

相反,Json 格式使用 ODataConventionalEntityMetadataBuilder,它返回与非计算操作连接的计算操作:

internal override IEnumerable<ODataAction> GetActions()
{
DebugUtils.CheckNoExternalCallers();
return ODataUtilsInternal.ConcatEnumerables(this.entryMetadataContext.Entry.NonComputedActions, this.MissingOperationGenerator.GetComputedActions());
}

对于计算操作,我们结束了在 EdmLibraryExtensions 中调用此扩展函数:

internal static string FullName(this IEdmEntityContainerElement containerElement)
{
Debug.Assert(containerElement != null, "containerElement != null");

return containerElement.Container.Name + "." + containerElement.Name;
}

所以我认为这里最好不要返回 container.Name,只返回 containerElement.Name。在 github 中解决问题并发布正式版本之前,运行具有此最小更改的 Microsoft OData 库的修补版本可以避免该问题。

关于c# - WebApi OData v3 OperationDescriptor 根据格式(atom vs json)返回不同的标题/目标 URI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29629758/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com