1

I am creating a web API Service but I am having some problems when it comes to calling HTTP Patch requests. Though I know how to create them. If you could help me with this I would appreciate it, here is my code:

HTTP PATCH CODE:

[HttpPatch("{username}")]
        public async Task<ActionResult> Patch(string username, [FromBody] JsonPatchDocument<User> patchDocument)
        { 
            //If no info has been passed, this API call will return badrequest
            if (patchDocument == null)
                return BadRequest();

            var theUser = await connection.GetAUser(username);
            var originalUser = await connection.GetAUser(username);

            if (theUser == null)
                return NotFound();

            //Changes specified in the patchdocument are applied to the user
            patchDocument.ApplyTo(theUser, ModelState);
            //check if the patching has been successful or not
            bool isValid = TryValidateModel(theUser);

            if (!isValid)
                return BadRequest(ModelState);
            else
            {
                bool check = await connection.UpdateUser(originalUser, theUser);
                if (check != true)
                    return BadRequest();
                else
                    return Ok();
            }

        }

Corelation with SQL Database (Method called from the previous code):

        public async Task<bool> UpdateUser(User originalUser, User patchedUser)
        {
            SqlCommand sqlCommand = new SqlCommand();
            try
            {
                if (originalUser.password != patchedUser.password)
                {
                    //string command = SQL COMMAND
                    SqlParameter param1 = new SqlParameter();
                    param1.ParameterName = "@password";
                    param1.Value = patchedUser.password;
                    SqlParameter param2 = new SqlParameter();
                    param2.ParameterName = "@username";
                    param2.Value = patchedUser.username;

                    sqlCommand.CommandText = command;
                    sqlCommand.Parameters.Add(param1);
                    sqlCommand.Parameters.Add(param2);

                    connection = new DataBaseConnectionService(configuration, sqlCommand);
                    await connection.GetData();
                }
                else
                    return true;
                return true;
            }
            catch (Exception error)
            {
                return false;
            }
        }

I have tested it on PostMan, and it works perfectly. The problem is that I know how to pass a JsonPatchDocument FromBody on PostMan, but I don't know how to do it using C# (I need this to make the call from an APP). I have tried to look for answers regarding this issue, but I have only found information about how to create the API, not about how to call it from C#. That is all, if you need any more information I will provide it as soon as I see your request, thank you all so much for your time, I hope everyone has good day.

EDIT: After diving deeper into this matter, I have found a way that could work, however It returns me a 405 status code ("Method not allowed"): This is the code that I use in my C# App

        public async Task<string> PatchUser(UserModel User_Raw)
        {
            if (client == null)
                InitializeClient();

            try
            {
                //converts the UserModel to JsonPatchDocument<UserModel>
                JsonPatchDocument<UserModel> body = new JsonPatchDocument<UserModel>();
                body.Replace(e = e, User_Raw);

                //Converts the JsonPatchDocument<UserModel> to Json
                var serializedJsonDocument = JsonConvert.SerializeObject(body);
                var stringUser = new StringContent(serializedJsonDocument, UnicodeEncoding.UTF8, "application/json");

                //
                var request = new HttpRequestMessage(new HttpMethod("PATCH"), "Here goes the URL");
                request.Content = stringUser;

                //response stores the Post result to later ensure that it has been successful
                var response = await client.SendAsync(request);
                response.EnsureSuccessStatusCode();

                string HttpResponse = await response.Content.ReadAsStringAsync();
                return HttpResponse;
            }
            catch (HttpRequestException error)
            {
                return null;
            }
            catch (Exception error)
            {
                jsonResult = null;
                return jsonResult;
            }
        }
JaimeSantos
  • 13
  • 1
  • 1
  • 4

1 Answers1

6

Are you asking how to make a PATCH request from a C# application? In that case, why are you showing all the irrelevant server code?

To make a PATCH request, you instantiate an HttpClient, and then do this:

    JsonPatchDocument<User> body = <...>;
    HttpResponseMessage response = await client.PatchAsync(requestUri, body);

If you're stuck with .NET Framework, you won't have PatchAsync, in which case you have to do something like this:

    var request = new HttpRequestMessage(new HttpMethod("PATCH"), requestUri) {
        Content = body
    };
    var response = await client.SendAsync(request);
Mo B.
  • 5,307
  • 3
  • 25
  • 42
  • I showed it because I did not know if it could be relevant or not. I cant use PatchAsync, I don't know why, but it doesn't appear when I use net.http.httpclient – JaimeSantos Nov 30 '20 at 18:11
  • @JaimeSantos I extended the answer. Does that help? – Mo B. Nov 30 '20 at 19:33
  • I updated the question trying this, summarizing it, it gave me a 405 error. I could not assign the JsonPatchDocument to the content of the HttpRequestMessage, so I did a couple of things to convert it into a StringContent. I have probably made the conversion wrongly, If you could check it out I would appreciate it. Thank you for your help so far, I feel like I almost got it (: – JaimeSantos Nov 30 '20 at 21:50
  • @JaimeSantos I don't think it's got anything to do with the body (to debug, use a method that doesn't take any body parameter). 405 means that the method is not allowed. If you are hosting on IIS, you may have to edit the web.config: https://stackoverflow.com/questions/19162825/web-api-put-request-generates-an-http-405-method-not-allowed-error – Mo B. Dec 01 '20 at 09:13
  • Never mind, I was using the wrong URL, I tried it again and it worked just fine, thank you so much for your help ((((: – JaimeSantos Dec 02 '20 at 19:50