PATCH method

dreezdreez Member Posts: 72
edited 2020-02-14 in NAV Tips & Tricks
Hi!

I have recently encountered a problem with PATCH call from C/AL.
I have already tried a solution for AL, but it didn't work, here's my code:
CASE RestMethod OF
 'PATCH':
    BEGIN
       String := 'PATCH' //it's a DotNet String variable
       HttpRequestMessage.Content(HttpContent); //HttpContent contains  JSON object which I sent
       HttpRequestMessage.Method(String); //I've tried to use ('PATCH') instead of String, but it requires DotNet variable
       HttpResponseMessage := HttpClient.SendAsync(HttpRequestMessage);
    END;
END;

When I try to execute that, I am getting the following error:

A call to System.Net.Http.HttpRequestMessage.set_Method failed with this message: The type of one or more arguments does not match the method's parameter type.

Any ideas?

Thanks in advance.

Best Answer

  • ShaiHuludShaiHulud Member Posts: 228
    edited 2020-02-13 Answer ✓
    dreez wrote: »
    Unfortunately that didn't help.
    A call to System.Uri failed with this message: Invalid URI: The format of the URI could not be determined.

    Is there any possibility to lookup how is, for example HttpClient.PutAsync method built?
    I feel like I'm giving up, and maybe I could just use this PATCH method with REST Sharp library, that you have recommended..

    Oh, looks like System.Uri needs absolute path, aka
    MethodUri := MethodUri.Uri(BaseUrl + Method);
    
    And, naturally, make sure that either your BaseUrl ends with, or Method begins, with a slash

Answers

  • ShaiHuludShaiHulud Member Posts: 228
    edited 2020-02-11
    HttpRequestMessage.Method requires a parameter (if setting a value) of type "HttpMethod", not "String". Once you have defined your variable (preferably with name "HttpMethod", your problematic line should be:
    HttpRequestMessage.Method(HttpMethod.Patch);
    
  • dreezdreez Member Posts: 72
    ShaiHulud wrote: »
    HttpRequestMessage.Method requires a parameter (if setting a value) of type "HttpMethod", not "String". Once you have defined your variable (preferably with name "HttpMethod", your problematic line should be:
    HttpRequestMessage.Method(HttpMethod.Patch);
    


    Thank you for your answer, but unfortunately I've already tried that.
    There is no such method as Patch - and that's the problem. There are methods like Get, Put and Post.

    My code is inspired by this topic (hopefuly it's not a problem to link something from outside of this forum):
    Patch_method_AL
  • ShaiHuludShaiHulud Member Posts: 228
    Ah, I see. You're using the HttpRequestMessage (and HttpMethod) from the "System.Net.Http" namespace (in which HttpMethod does not have PATCH method), while I checked the "Windows.Web.Http".

    You should try then (should work in theory):
    HttpMethod := HttpMethod.HttpMethod('PATCH');
    HttpRequestMessage.Method(HttpMethod);
    

    Alternatively, you could go with RestSharp library.
  • dreezdreez Member Posts: 72
    edited 2020-02-11
    Thanks, I feel like it's really close solution, because now I am getting the following error:
    A call to System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode failed with this message: Response status code does not indicate success: 302 (Found).

    I think, that I know what's the reason, but I don't know how to fix the problem.
    I will show you my entire code, so I can explain:
    LOCAL CallRESTWebService()
    HttpClient := HttpClient.HttpClient;
    HttpClient.BaseAddress := Uri.Uri(BaseUrl);
    IF AuthorizationHeader <> '' THEN
      HttpClient.DefaultRequestHeaders.Add('Authorization',AuthorizationHeader);
    
    CASE RestMethod OF
      'GET':
        CurrHttpResponseMessage := HttpClient.GetAsync(Method).Result;
      'POST':
        CurrHttpResponseMessage := HttpClient.PostAsync(Method,HttpContent).Result;
      'PUT':
        CurrHttpResponseMessage := HttpClient.PutAsync(Method,HttpContent).Result;
      'DELETE':
        CurrHttpResponseMessage := HttpClient.DeleteAsync(Method).Result;
      'PATCH':
        BEGIN
           HttpRequestMessage := HttpRequestMessage.HttpRequestMessage;
           HttpMethod := HttpMethod.HttpMethod('PATCH');
           HttpRequestMessage.Content(HttpContent);
           HttpRequestMessage.Method(HttpMethod); 
           CurrHttpResponseMessage := HttpClient.SendAsync(HttpRequestMessage).Result;
        END;
    END;
    CurrHttpResponseMessage.EnsureSuccessStatusCode;
    

    And maybe a little explanation here, RestMethod, as you can see is GET, POST, PUT, DELETE or PATCH. Also there is a Method (query) that I can use with API, for example 'api/employees' and I can combine that with different queries.
    As you can see, HttpClient.Get/Post/Put/Delete methods takes this Method as a parameter, so now I don't know where to put this Method variable, so it could work with newly defined PATCH case.
    I have tried something like:
    HttpMethod := HttpMethod.HttpMethod('PATCH ' + Method);
    
    but it doesn't work and results with following error:
    A call to System.Net.Http.HttpMethod failed with this message: The format of the HTTP method is invalid.

    Do you have any idea how to fix that?
  • ShaiHuludShaiHulud Member Posts: 228
    You should add the "Method" as part of your HttpRequestMessage.RequestUri property, which states that:
    If the request Uri is a relative Uri, it will be combined with the BaseAddress [of the HttpClient]
    So you'd have a line
    HttpRequestMessage.RequestUri(Method);
    

    Sorry I can't test these things, don't have a proper platform with PATCH methods
  • dreezdreez Member Posts: 72
    edited 2020-02-13
    ShaiHulud wrote: »
    Sorry I can't test these things, don't have a proper platform with PATCH methods
    That's not a problem. You're actually really helpful and patient, so I'm really thankful for that.
    ShaiHulud wrote: »
    So you'd have a line
    HttpRequestMessage.RequestUri(Method);
    

    The thing is, that the method RequestUri requires a DotNet parameter, while my Method is a text.
    I've just tried to do that the same way as before, so I added two lines:
    HttpMethod2 := HttpMethod2.HttpMethod(Method);
    HttpRequestMessage.RequestUri(HttpMethod2);
    
    But it doesn't seem to work and results with an error:
    A call to System.Net.Http.HttpMethod failed with this message: The format of the HTTP method is invalid.
  • ShaiHuludShaiHulud Member Posts: 228
    Alright, how about:
    <..>
      'PATCH':
        BEGIN
           HttpRequestMessage := HttpRequestMessage.HttpRequestMessage;
           HttpMethod := HttpMethod.HttpMethod('PATCH');
           HttpRequestMessage.Content(HttpContent);
           HttpRequestMessage.Method(HttpMethod); 
           MethodUri := MethodUri.Uri(Method);
           HttpRequestMessage.RequestUri(MethodUri);
           CurrHttpResponseMessage := HttpClient.SendAsync(HttpRequestMessage).Result;
        END;
    <..>
    
    Where:
    Name	DataType	Subtype	Length
    MethodUri	DotNet	System.Uri.'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'	
    
  • dreezdreez Member Posts: 72
    Unfortunately that didn't help.
    A call to System.Uri failed with this message: Invalid URI: The format of the URI could not be determined.

    Is there any possibility to lookup how is, for example HttpClient.PutAsync method built?
    I feel like I'm giving up, and maybe I could just use this PATCH method with REST Sharp library, that you have recommended..
  • ShaiHuludShaiHulud Member Posts: 228
    edited 2020-02-13 Answer ✓
    dreez wrote: »
    Unfortunately that didn't help.
    A call to System.Uri failed with this message: Invalid URI: The format of the URI could not be determined.

    Is there any possibility to lookup how is, for example HttpClient.PutAsync method built?
    I feel like I'm giving up, and maybe I could just use this PATCH method with REST Sharp library, that you have recommended..

    Oh, looks like System.Uri needs absolute path, aka
    MethodUri := MethodUri.Uri(BaseUrl + Method);
    
    And, naturally, make sure that either your BaseUrl ends with, or Method begins, with a slash
  • dreezdreez Member Posts: 72
    ShaiHulud wrote: »

    Oh, looks like System.Uri needs absolute path, aka
    MethodUri := MethodUri.Uri(BaseUrl + Method);
    
    And, naturally, make sure that either your BaseUrl ends with, or Method begins, with a slash

    That works!
    Thank you so much for helping me!

Sign In or Register to comment.