2

我有一个 WebService 公开这个$metadata

<?xml version="1.0" encoding="UTF-8" standalone="true"?>
<edmx:Edmx xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" Version="1.0">     > <edmx:DataServices m:DataServiceVersion="1.0"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">

<Schema xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
xmlns="http://schemas.microsoft.com/ado/2007/05/edm"
xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
Namespace="NAV"> 
<EntityType Name="PAsset"> 
<Key> <PropertyRef Name="No"/> </Key>  <Property Name="No" Nullable="false" Type="Edm.String"/>  <Property Name="Description"
Nullable="true" Type="Edm.String"/>  <Property Name="Inactive"
Nullable="false" Type="Edm.Boolean"/>  <Property Name="Insured"
Nullable="false" Type="Edm.Boolean"/> </EntityType> 

<EntityType Name="PAssetsDepreciationBook">

<EntityType Name="PBankAPostGrp">
<EntityType Name="PCompany">
<EntityType Name="PCustomer">

$metadata是否可以在 C# 应用程序中获取其中的信息?

我有一个引用服务工作的应用程序,以及我正在使用的一些代码:

uriString = String.Format("PAssetsDepreciationBook?$filter=FA_No eq '{0}'",cliente);

contex = new ServiceReference1.NAV(new Uri(serviceEndPoint)); contex.Credentials = CredentialCache.DefaultCredentials;

var customers = contex.Execute(new Uri(uriString, UriKind.Relative));

foreach (var c in customers) { result = result + c.Acquisition_Cost; } 返回结果;

这工作正常,但得到$metadata没有。

4

3 回答 3

5

已经有代码(大部分)可以做到这一点。它涉及ODataMessageReader.ReadMetadataDocument()调用:

var request = WebRequest.CreateHttp(baseUrl + "$metadata");
var metadataMessage =
    new ClientHttpResponseMessage((HttpWebResponse)request.GetResponse());
using (var messageReader = new ODataMessageReader(metadataMessage))
{
    IEdmModel edmModel = messageReader.ReadMetadataDocument();
    // Do stuff with edmModel here
}

您需要 ClientHttpResponseMessage 类,但这很简单(来自ODataLib101):

public class ClientHttpResponseMessage : IODataResponseMessage
{
    private readonly HttpWebResponse webResponse;

    public ClientHttpResponseMessage(HttpWebResponse webResponse)
    {
        if (webResponse == null)
            throw new ArgumentNullException("webResponse");
        this.webResponse = webResponse;
    }

    public IEnumerable<KeyValuePair<string, string>> Headers
    {
        get
        {
            return this.webResponse.Headers.AllKeys.Select(
                headerName => new KeyValuePair<string, string>(
                   headerName, this.webResponse.Headers.Get(headerName)));
        }
    }

    public int StatusCode
    {
        get { return (int)this.webResponse.StatusCode; }
        set
        {
            throw new InvalidOperationException(
                "The HTTP response is read-only, status code can't be modified on it.");
        }
    }

    public Stream GetStream()
    {
        return this.webResponse.GetResponseStream();
    }

    public string GetHeader(string headerName)
    {
        if (headerName == null)
            throw new ArgumentNullException("headerName");
        return this.webResponse.Headers.Get(headerName);
    }

    public void SetHeader(string headerName, string headerValue)
    {
        throw new InvalidOperationException(
            "The HTTP response is read-only, headers can't be modified on it.");
    }
}

使用 IEdmModel,您可以访问元数据中的所有信息以执行诸如构建类型->控制器名称的字典之类的操作:

Dictionary<type, string> typeControllerMap =
    edmModel.SchemaElements.OfType<IEdmEntityContainer>()
            .Single()
            .Elements.OfType<IEdmEntitySet>()
            .Select(es => new { t = FindType(es.ElementType.FullName()), n = es.Name })
            .Where(tn => tn.t != null)
            .ToDictionary(tn => tn.t, tn => tn.n);

上面 LINQ 链中间的FindType()调用只是在所有程序集中搜索给定类型名称的类型:

private static Type FindType(string fullName)
{
    return
        AppDomain.CurrentDomain.GetAssemblies()
            .Where(a => !a.IsDynamic)
            .SelectMany(a => a.GetTypes())
            .FirstOrDefault(t => t.FullName.Equals(fullName));
}
于 2014-01-03T15:40:13.883 回答
1

例如,您可以将元数据请求为纯 XML HttpWebRequest。如果你需要解析它,你可以使用可以在上面找到的EdmLib( ),甚至更好的()也可以在上面找到。专门设计用于读取这些(它仍然为它返回 EDM 对象模型,它只是为您处理包装器和版本控制)。Microsoft.Data.Edm.dllNuGetODataLibMicrosoft.Data.OData.dllNugetODataMessageReaderReadMetadataDocumentEDMX

于 2012-07-03T15:44:21.047 回答
1

谢谢,它工作得很好。

像这样:

// Create a request for the URL. 
WebRequest request = WebRequest.Create("http://localhost:7048/DynamicsNAV70/OData/$metadata");

//set the credentials.
request.Credentials = CredentialCache.DefaultCredentials;

// Get the response.
WebResponse response = request.GetResponse();

// Get the stream containing content returned by the server.
Stream dataStream = response.GetResponseStream();

// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);

// Read the content.
string responseFromServer = reader.ReadToEnd();

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(new StringReader(responseFromServer));

// Clean up the streams and the response.
reader.Close();
response.Close();

在此之后,只需像 xml 文件一样解析数据。

于 2012-07-04T13:29:22.247 回答