Khon
Khon

Reputation: 275

How to change request body in IActionFilter in asp.net core

Currently I am sending encrypted request to asp.net core controller. The following is the request body structure:

{
  "body": "pEbXVvl1ue95eGQywK/q80cGHjYk+2VNPYEgnRgU+vI="
}

Before that I had implemented the filter IActionFilter so in OnActionExecuting(ActionExecutingContext context) where I decrypt the above mention request body(body key)

After decryption, I got the decrypted request body like below:

{
  "Urno":"URN123456"
}

After decryption, I want to pass decrypted request (mentioned above "Urno":"URN123456") body to controller

I had tried to convert the string to byte than pass it to Request.body but no success:

public void OnActionExecuting(ActionExecutingContext context)
{
    var request = context.HttpContext.Request;
    request.EnableRewind();
    request.Body.Position = 0;
    using (var reader = new StreamReader(request.Body))
    {                   
        var bodyString = reader.ReadToEnd(); //{ "body": "pEbXVvl1ue95eGQywK/q80cGHjYk+2VNPYEgnRgU+vI="}
        if (bodyString != "")
        {
             var data = JObject.Parse(bodyString);
             var key = data.GetValue("body"); 
             var keybytes = Encoding.UTF8.GetBytes("808080808080808011");
             var iv = Encoding.UTF8.GetBytes("8080808080808080111");
             var encrypted = Convert.FromBase64String(key.ToString());
             var decriptedFromJavascript = DecryptStringFromBytes(encrypted, keybytes, iv); //{ "Urno":"URN123456"}
             byte[] bytes = Encoding.ASCII.GetBytes(decriptedFromJavascript);
             request.Body = new MemoryStream(bytes); // here i am trying to change request body
        }
    }
}
   // controller
[HttpPost("[action]")]
public async Task<string> GetInvestorUrno(Urnoinvestor InfoReq){

}


// class
public class Urnoinvestor 
{
    public string Urno{ get; set; }
}

I want to change request body and pass the decrypted request to controller

Upvotes: 7

Views: 5564

Answers (2)

Edward
Edward

Reputation: 30026

For your scenario, IActionFilter would not work. Check this image:

enter image description here

The Model binding is run before ActionFilter which means no matter what you changed to the body, it would not change the model. You need to try the filter before Model binding like Resource filter.

  1. Change to Resource filter

    public class RequestBodyFilter : IResourceFilter
    {
        public void OnResourceExecuted(ResourceExecutedContext context)
        {
            //throw new NotImplementedException();
        }
    
        public void OnResourceExecuting(ResourceExecutingContext context)
        {
            var request = context.HttpContext.Request;
            request.EnableRewind();
            request.Body.Position = 0;
            using (var reader = new StreamReader(request.Body))
            {
                var decriptedFromJavascript = "{ \"Urno\":\"URN123456\"}"; //{ "Urno":"URN123456"}
                byte[] bytes = Encoding.ASCII.GetBytes(decriptedFromJavascript);
                request.Body = new MemoryStream(bytes); // here i am trying to change request body
            }
        }
    }
    
  2. Since you are binding from body, you need to specify the action with [FromBody] as the suggestion from @Tony Abrams.

    [HttpPost("[action]")]
    [TypeFilter(typeof(RequestBodyFilter))]
    public async Task<string> GetInvestorUrno([FromBody]Urnoinvestor InfoReq)
    {
        return InfoReq.Urno;
    }
    

Upvotes: 12

Tony Abrams
Tony Abrams

Reputation: 4673

You don't have the parameter marked as from body, so it's not loading the data from the request body. Instead it's expecting it in the URI.

Try this instead:

[HttpPost("[action]")]
public async Task<string> GetInvestorUrno([FromBody]Urnoinvestor InfoReq){

}

Upvotes: -1

Related Questions