Skip to content

[DocumentIntelligence] DPG: properties incorrectly defined as GUID in the REST API spec #41671

Open
@kinelski

Description

@kinelski

The REST API spec incorrectly defines some string properties as GUIDs, but they should be generic strings. This makes our deserialization code fail during runtime.

As a workaround, we are forcibly making them strings with manually written C# code. Ideally we should get the spec fixed and get the custom pieces of code removed.

Exhaustive list of custom code added:

  • OperationId property in OperationDetails:

    // CUSTOM CODE NOTE: the spec incorrectly defines the OperationId property as a GUID,
    // but it should be a string. This makes our deserialization code fail. Ideally we'll
    // get the spec fixed and this piece of custom code will be removed.
    /// <summary> Operation ID. </summary>
    public string OperationId { get; }

  • CodeGenSuppress attributes in DocumentModelAdministrationClient:

    [CodeGenSuppress("GetOperationAsync", typeof(Guid), typeof(CancellationToken))]
    [CodeGenSuppress("GetOperation", typeof(Guid), typeof(CancellationToken))]
    [CodeGenSuppress("GetOperationAsync", typeof(Guid), typeof(RequestContext))]
    [CodeGenSuppress("GetOperation", typeof(Guid), typeof(RequestContext))]

  • operationId parameter in GetOperation methods in DocumentModelAdministrationClient:

    // CUSTOM CODE NOTE: the spec incorrectly defines the operationId parameter as a GUID
    // in the GetOperation APIs, but it should be a string. This makes it impossible to
    // use the API since IDs will never be a GUID. Because of this we're manually adding
    // overloads that take a string and forcing the generated ones to be suppressed. Ideally
    // we'll get the spec fixed and this piece of custom code will be removed.
    /// <summary> Gets operation info. </summary>
    /// <param name="operationId"> Operation ID. </param>
    /// <param name="cancellationToken"> The cancellation token to use. </param>
    /// <include file="Generated/Docs/DocumentIntelligenceAdministrationClient.xml" path="doc/members/member[@name='GetOperationAsync(Guid,CancellationToken)']/*" />
    public virtual async Task<Response<OperationDetails>> GetOperationAsync(string operationId, CancellationToken cancellationToken = default)
    {
    RequestContext context = FromCancellationToken(cancellationToken);
    Response response = await GetOperationAsync(operationId, context).ConfigureAwait(false);
    return Response.FromValue(OperationDetails.FromResponse(response), response);
    }
    /// <summary> Gets operation info. </summary>
    /// <param name="operationId"> Operation ID. </param>
    /// <param name="cancellationToken"> The cancellation token to use. </param>
    /// <include file="Generated/Docs/DocumentIntelligenceAdministrationClient.xml" path="doc/members/member[@name='GetOperation(Guid,CancellationToken)']/*" />
    public virtual Response<OperationDetails> GetOperation(string operationId, CancellationToken cancellationToken = default)
    {
    RequestContext context = FromCancellationToken(cancellationToken);
    Response response = GetOperation(operationId, context);
    return Response.FromValue(OperationDetails.FromResponse(response), response);
    }
    /// <summary>
    /// [Protocol Method] Gets operation info.
    /// <list type="bullet">
    /// <item>
    /// <description>
    /// This <see href="https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/samples/ProtocolMethods.md">protocol method</see> allows explicit creation of the request and processing of the response for advanced scenarios.
    /// </description>
    /// </item>
    /// <item>
    /// <description>
    /// Please try the simpler <see cref="GetOperationAsync(string,CancellationToken)"/> convenience overload with strongly typed models first.
    /// </description>
    /// </item>
    /// </list>
    /// </summary>
    /// <param name="operationId"> Operation ID. </param>
    /// <param name="context"> The request context, which can override default behaviors of the client pipeline on a per-call basis. </param>
    /// <exception cref="RequestFailedException"> Service returned a non-success status code. </exception>
    /// <returns> The response returned from the service. </returns>
    /// <include file="Generated/Docs/DocumentIntelligenceAdministrationClient.xml" path="doc/members/member[@name='GetOperationAsync(Guid,RequestContext)']/*" />
    public virtual async Task<Response> GetOperationAsync(string operationId, RequestContext context)
    {
    using var scope = ClientDiagnostics.CreateScope("DocumentIntelligenceAdministrationClient.GetOperation");
    scope.Start();
    try
    {
    using HttpMessage message = CreateGetOperationRequest(operationId, context);
    return await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false);
    }
    catch (Exception e)
    {
    scope.Failed(e);
    throw;
    }
    }
    /// <summary>
    /// [Protocol Method] Gets operation info.
    /// <list type="bullet">
    /// <item>
    /// <description>
    /// This <see href="https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/samples/ProtocolMethods.md">protocol method</see> allows explicit creation of the request and processing of the response for advanced scenarios.
    /// </description>
    /// </item>
    /// <item>
    /// <description>
    /// Please try the simpler <see cref="GetOperation(string,CancellationToken)"/> convenience overload with strongly typed models first.
    /// </description>
    /// </item>
    /// </list>
    /// </summary>
    /// <param name="operationId"> Operation ID. </param>
    /// <param name="context"> The request context, which can override default behaviors of the client pipeline on a per-call basis. </param>
    /// <exception cref="RequestFailedException"> Service returned a non-success status code. </exception>
    /// <returns> The response returned from the service. </returns>
    /// <include file="Generated/Docs/DocumentIntelligenceAdministrationClient.xml" path="doc/members/member[@name='GetOperation(Guid,RequestContext)']/*" />
    public virtual Response GetOperation(string operationId, RequestContext context)
    {
    using var scope = ClientDiagnostics.CreateScope("DocumentIntelligenceAdministrationClient.GetOperation");
    scope.Start();
    try
    {
    using HttpMessage message = CreateGetOperationRequest(operationId, context);
    return _pipeline.ProcessMessage(message, context);
    }
    catch (Exception e)
    {
    scope.Failed(e);
    throw;
    }
    }

  • operationId parameter in the internal CreateGetOperationRequest method in DocumentModelAdministrationClient:

    internal HttpMessage CreateGetOperationRequest(string operationId, RequestContext context)
    {
    var message = _pipeline.CreateMessage(context, ResponseClassifier200);
    var request = message.Request;
    request.Method = RequestMethod.Get;
    var uri = new RawRequestUriBuilder();
    uri.Reset(_endpoint);
    uri.AppendRaw("/documentintelligence", false);
    uri.AppendPath("/operations/", false);
    uri.AppendPath(operationId, true);
    uri.AppendQuery("api-version", _apiVersion, true);
    request.Uri = uri;
    request.Headers.Add("Accept", "application/json");
    return message;
    }

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions