0

I am making a post call to my .net core api from client using httpclient class, my api hosted on Azure. When payload passed to api comntroler method with simple data without any special charcters call get succesfully executed, but when call made with special charcters like "%`` it get reject with status code forbidden by api gateways. We cannot change Azure api gatway policy, so some how I need to change my post data content to send special charcters in post method.

Client Call Sample

using System;
class Program
{
    static void Main(string[] args)
    {
        Task.Run(() => MainAsync());
        Console.ReadLine();
    }
    static async Task MainAsync()
    {
        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri("https://postCallPoc.net");
            var emp = new Employee()
            {
                Name = "Jhon",
                Address = "%House no 20, near Clutch & Gair showroom Mumbai", 
                DOJ = DateTime.Now.Date,
                Note = "%Verificaion Pending"
            };

            var httpContent = GetSerializeContent(emp);
            var result = await client.PostAsync("/api/Employee/add", httpContent);

            Console.WriteLine(result.StatusCode); //receiving the responce as Forbidden

        }
    }

    public class Employee
    {
        public int? ID { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public DateTime DOJ { get; set; }
        public string Note { get; set; }
    }
}

HTPP Content Creator

private StringContent GetSerializeContent(dynamic content)
        {
            var serilizedContent = JsonConvert.SerializeObject(content);
            //var buffer = System.Text.Encoding.UTF8.GetBytes(serilizedContent);
            var result = new StringContent(serilizedContent,  System.Text.Encoding.UTF8);
            result.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            return result;
        }

API Controler

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using DA.Common.Master;
using DataEntity;
using ApiCommon;
using Common;

namespace MasterData.Controllers
{
    [ApiController]
    [Route("api/[controller]/[action]")]
    [Consumes("application/json")]
    [Produces("application/json")]
    public class EmployeeController : ControllerBase
    {
        ILogger<EmployeeController> _logger;
        public EmployeeController( ILogger<EmployeeController> logger) 
        {
            _logger = logger;
        }


        [HttpPost]
        public ActionResult<ApiResponse> Add(Employee emp)
        {

            ApiResponse response;
            try
            {

                var dbResponce = EmpoyeeBal.Insatnce.Save(emp);
                response = new ApiResponse
                {
                    Data = dbResponce
                };

                return Ok(response);


            }
            catch (Exception ex)
            {
                _logger.Log(ex);
            }
        }

    }
}

ERROR

403 Forbidden

403 Forbidden


Microsoft-Azure-Application-Gateway/v2
Neeraj Kumar Gupta
  • 2,157
  • 7
  • 30
  • 58
  • Can you show your add API pls? Do you have a control over API action code? – Serge Mar 18 '23 at 08:24
  • I'm surprised that even compiles at the moment - all the `HttpClient.PostAsync` overloads accept an `HttpContent` as the second parameter, and you've got an `Employee`. Is there some extension method you're using? (The code doesn't compile for me at the moment.) – Jon Skeet Mar 18 '23 at 08:41
  • I somehow suspect you have this problem: https://stackoverflow.com/questions/81991/a-potentially-dangerous-request-form-value-was-detected-from-the-client is your client setting the content-type to JSON and you are sending a JSON payload in the body, right? – rene Mar 18 '23 at 08:41
  • hi @Serge, added api controller code in my orignal post, When I receive Forbidden responce it does not reach to API controller I checked through log, but when we run service in locallhost everything works fine, problem is when we host service on our Azure server .. and connect from our client with special charcters in payload – Neeraj Kumar Gupta Mar 18 '23 at 08:42
  • yes @JonSkeet, there is extension that translates Employee to HttpContent – Neeraj Kumar Gupta Mar 18 '23 at 08:45
  • So where is that extension method? We have no idea what it's doing at the moment. – Jon Skeet Mar 18 '23 at 08:46
  • @JonSkeet Added the method that generates the HttpContent – Neeraj Kumar Gupta Mar 18 '23 at 08:52
  • 1
    Right. Not sure why you're using a `ByteArrayContent` rather than `StringContent` (given that this is text data) but that at least makes it clearer. Could you give more detail about the API gateway that's causing an issue? Even if you can't change it, knowing more about it would be helpful. – Jon Skeet Mar 18 '23 at 09:05
  • Exactly, you can [specify UTF-8 encoding](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.stringcontent.-ctor?view=net-8.0#system-net-http-stringcontent-ctor(system-string-system-text-encoding-system-net-http-headers-mediatypeheadervalue)) in the `StringContent` – Pieterjan Mar 18 '23 at 09:33
  • You can use System.Net.WebUtility.HtmlEncode(string) to encode special character or use GZIP to which will convert entire message to acceptable characters. – jdweng Mar 18 '23 at 09:35
  • @JonSkeet, @Pieterjan changin ByteArrayContent to StringContent worked for charecter & but for "` still having same issue – Neeraj Kumar Gupta Mar 18 '23 at 09:45
  • @jdweng: This is JSON, not HTML, and the content type is application/json. It shouldn't be HTML-encoded. – Jon Skeet Mar 18 '23 at 09:54
  • @NeerajKumarGupta: I'm very surprised that changing from ByteArrayContent to StringContent changed things at all. I suggest you use Fiddler or something similar to compare the *actual* body you're sending with those two options. – Jon Skeet Mar 18 '23 at 09:54
  • @JonSkeet : Issue has to be encoding. JSON has special characters that need to be escaped. When sending bytes these character may not get escaped properly. See : https://www.tutorialspoint.com/json_simple/json_simple_escape_characters.htm. When not specifying the encoding you could get unmatched single quotes when unicode characters are in data and using bytes. – jdweng Mar 18 '23 at 10:14
  • @jdweng: The OP is calling `JsonConvert.SerializeObject`. That should be doing all the escaping required. They're currently then encoding that string as UTF-8, which is expected to be the default encoding for JSON. In other words, it should work fine, IMO. (And using HTML encoding is *definitely* not appropriate - and nor is GZIP, which applies compression rather than encoding...) – Jon Skeet Mar 18 '23 at 10:25
  • @JonSkeet, I understood the pattern of failure now, I tried with PostMan to understand the issue, if I am sending payload with % sign like Address = "%Test Address" And Note="%TestNote" then its failing but when passing like Address = "%Test Address" And Note="% TestNote" same thing with sigle coute ` charecter. I add the error that I am receiving in postman – Neeraj Kumar Gupta Mar 18 '23 at 13:08
  • Are you even remotely trying what I'm saying? [Docs](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.headers.mediatypeheadervalue.-ctor?view=net-8.0#system-net-http-headers-mediatypeheadervalue-ctor(system-string-system-string)) - `new MediaTypeHeaderValue("application/json", Encoding.UTF8)` - Just try it, it'll work – Pieterjan Mar 18 '23 at 14:22
  • And I still think you should just use [`StringContent`](https://learn.microsoft.com/en-us/dotnet/api/system.net.http.stringcontent.-ctor?view=net-7.0#system-net-http-stringcontent-ctor(system-string-system-text-encoding-system-net-http-headers-mediatypeheadervalue)) - `await httpClient.PostAsync(url, new StringContent(serilizedContent, Encoding.UTF8, "application/json"))`. You don't need to set the content-type header anymore after that – Pieterjan Mar 18 '23 at 14:27
  • 1
    Yes, @Pieterjan if you look my post I changed that as well, please look my previous comment to JonSkeet, I tried multiple payload with Postman and same issue occuring, – Neeraj Kumar Gupta Mar 18 '23 at 16:01
  • @Pieterjan this is same issue reported here, but at my end WAF policy is not going to relax, now I am not sure how to fix this issue https://stackoverflow.com/questions/66821199/error-403-forbidden-microsoft-azure-application-gateway-v2 – Neeraj Kumar Gupta Mar 18 '23 at 17:33

0 Answers0