madskristensen / RestClientVS

Other
66 stars 14 forks source link

Add Missing Rest PATCH method #24

Closed garywoodfine closed 2 years ago

garywoodfine commented 2 years ago

Describe the bug The REST PATCH method is missing

To Reproduce

Trying to write a .http test method as follows

###
PATCH {{host}}/{{organisation_resource_name}}/{{organisation_id}}
Content-Type: application/json-patch+json; ext=jsonpatch
Accept:  application/json-patch+json; ext=jsonpatch
[
  {
    "op": "replace",
    "value": "Fantastic org name",
    "path": "name"
  }
]
###

Expected behavior Should be able to execute a PATCH method

Screenshots If applicable, add screenshots to help explain your problem.

Additional context

From what I can ascertain from the code the Method is missing from the IntellisenseCatalog.cs

below I have added what I think the option should be

 public static readonly IDictionary<string, string> HttpMethods = new Dictionary<string, string>()
        {
            {"GET",     "The GET method is used to retrieve information from the given server using a given URI.Requests using GET should only retrieve data and should have no other effect on the data."},
            {"HEAD",    "Same as GET, but transfers the status line and header section only."},
            {"POST",    "A POST request is used to send data to the server, for example, customer information, file upload, etc. using HTML forms"},
            {"PUT",     "Replaces all current representations of the target resource with the uploaded content."},
            {"DELETE",  "Removes all current representations of the target resource given by a URI."},
            {"TRACE",   "Performs a message loop-back test along the path to the target resource."},
            {"OPTIONS",  "Describes the communication options for the target resource."},
            {"PATCH", "Used to modify the values of the resource properties." }
        };
madskristensen commented 2 years ago

It's not just that, the issue is that the HttpClient in .NET doesn't seem to support it. So, even if we make it show up in IntelliSense, it can't send the actual request

garywoodfine commented 2 years ago

Doh! that is a major shortcoming of the HttpClient then!

I just had a quick look on SO and found this https://stackoverflow.com/questions/39816829/how-do-i-do-a-patch-request-using-httpclient-in-dotnet-core

I haven't verified the answer yet, but it seems one of the answers implies that PATCH was supported in .net 2.2 I'll try knock up a test project to test this hypothesis

garywoodfine commented 2 years ago

I can see in RequestSender.cs the GetMethod switch case may also present an issue because Patch is not an option on the HttpMethod , probably the version you reference in your package.

 private static HttpMethod GetMethod(string? methodName)
        {
            return methodName?.ToLowerInvariant() switch
            {
                "head" => HttpMethod.Head,
                "post" => HttpMethod.Post,
                "put" => HttpMethod.Put,
                "delete" => HttpMethod.Delete,
                "options" => HttpMethod.Options,
                "trace" => HttpMethod.Trace,

                _ => HttpMethod.Get,
            };
        }

When I browse the decompiled code of HttpMethod I can see it has been added

namespace System.Net.Http
{
  /// <summary>A helper class for retrieving and comparing standard HTTP methods and for creating new HTTP methods.</summary>
  public class HttpMethod : IEquatable<HttpMethod>
  {
    /// <summary>Initializes a new instance of the <see cref="T:System.Net.Http.HttpMethod" /> class with a specific HTTP method.</summary>
    /// <param name="method">The HTTP method.</param>
    public HttpMethod(string method);

    /// <summary>Represents an HTTP DELETE protocol method.</summary>
    /// <returns>Returns <see cref="T:System.Net.Http.HttpMethod" />.</returns>
    public static HttpMethod Delete { get; }

    /// <summary>Represents an HTTP GET protocol method.</summary>
    /// <returns>Returns <see cref="T:System.Net.Http.HttpMethod" />.</returns>
    public static HttpMethod Get { get; }

    /// <summary>Represents an HTTP HEAD protocol method. The HEAD method is identical to GET except that the server only returns message-headers in the response, without a message-body.</summary>
    /// <returns>Returns <see cref="T:System.Net.Http.HttpMethod" />.</returns>
    public static HttpMethod Head { get; }

    /// <summary>An HTTP method.</summary>
    /// <returns>An HTTP method represented as a <see cref="T:System.String" />.</returns>
    public string Method { get; }

    /// <summary>Represents an HTTP OPTIONS protocol method.</summary>
    /// <returns>Returns <see cref="T:System.Net.Http.HttpMethod" />.</returns>
    public static HttpMethod Options { get; }

    /// <summary>Gets the HTTP PATCH protocol method.</summary>
    /// <returns>The HTTP PATCH protocol method.</returns>
    public static HttpMethod Patch { get; }

    /// <summary>Represents an HTTP POST protocol method that is used to post a new entity as an addition to a URI.</summary>
    /// <returns>Returns <see cref="T:System.Net.Http.HttpMethod" />.</returns>
    public static HttpMethod Post { get; }

    /// <summary>Represents an HTTP PUT protocol method that is used to replace an entity identified by a URI.</summary>
    /// <returns>Returns <see cref="T:System.Net.Http.HttpMethod" />.</returns>
    public static HttpMethod Put { get; }

    /// <summary>Represents an HTTP TRACE protocol method.</summary>
    /// <returns>Returns <see cref="T:System.Net.Http.HttpMethod" />.</returns>
    public static HttpMethod Trace { get; }

    /// <summary>Determines whether the specified <see cref="T:System.Net.Http.HttpMethod" /> is equal to the current <see cref="T:System.Object" />.</summary>
    /// <param name="other">The HTTP method to compare with the current object.</param>
    /// <returns>
    /// <see langword="true" /> if the specified object is equal to the current object; otherwise, <see langword="false" />.</returns>
    public bool Equals([NotNullWhen(true)] HttpMethod? other);

    /// <summary>Determines whether the specified <see cref="T:System.Object" /> is equal to the current <see cref="T:System.Object" />.</summary>
    /// <param name="obj">The object to compare with the current object.</param>
    /// <returns>
    /// <see langword="true" /> if the specified object is equal to the current object; otherwise, <see langword="false" />.</returns>
    public override bool Equals([NotNullWhen(true)] object? obj);

    /// <summary>Serves as a hash function for this type.</summary>
    /// <returns>A hash code for the current <see cref="T:System.Object" />.</returns>
    public override int GetHashCode();

    /// <summary>The equality operator for comparing two <see cref="T:System.Net.Http.HttpMethod" /> objects.</summary>
    /// <param name="left">The left <see cref="T:System.Net.Http.HttpMethod" /> to an equality operator.</param>
    /// <param name="right">The right  <see cref="T:System.Net.Http.HttpMethod" /> to an equality operator.</param>
    /// <returns>
    /// <see langword="true" /> if the specified <paramref name="left" /> and <paramref name="right" /> parameters are equal; otherwise, <see langword="false" />.</returns>
    public static bool operator ==(HttpMethod? left, HttpMethod? right);

    /// <summary>The inequality operator for comparing two <see cref="T:System.Net.Http.HttpMethod" /> objects.</summary>
    /// <param name="left">The left <see cref="T:System.Net.Http.HttpMethod" /> to an inequality operator.</param>
    /// <param name="right">The right  <see cref="T:System.Net.Http.HttpMethod" /> to an inequality operator.</param>
    /// <returns>
    /// <see langword="true" /> if the specified <paramref name="left" /> and <paramref name="right" /> parameters are inequal; otherwise, <see langword="false" />.</returns>
    public static bool operator !=(HttpMethod? left, HttpMethod? right);

    /// <summary>Returns a string that represents the current object.</summary>
    /// <returns>A string representing the current object.</returns>
    public override string ToString();
  }

I realise your Package targets .net framework 4.8.

I'm not a Windows or Visual Studio tools developer, so I may obviously be wrong or assuming a whole lot of wrongs :-)

Thanks for faking the time to review my issue raised

madskristensen commented 2 years ago

If that updated package targets .NET Standard 2.0 then I can use it from Framework 4.8 code

garywoodfine commented 2 years ago

I think it does target .NET Standard 2.0

https://www.nuget.org/packages/System.Net.Http

madskristensen commented 2 years ago

Nope, just installed the latest System.Net.Http and it doesn't come with support for patch

madskristensen commented 2 years ago

It is only in netstandard 2.1 which isn't available to .NET 4.8 :(

madskristensen commented 2 years ago

Aha, I can create a new HttpMethod simply by doing this: var method = new HttpMethod("PATCH"). Fix incoming...

garywoodfine commented 2 years ago

@madskristensen AWESOME that works! really appreciate your time will make a donation to your sponsorship