locked
Calling action method inside another method RRS feed

  • Question

  • User-1104215994 posted

    Hello,

    I wonder if there is a way to programmatically call an action method inside of another one? <g class="gr_ gr_84 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling multiReplace" id="84" data-gr-id="84">Lets</g> say I have this controller below and I would like to call confirmation inside of initiation. Is this possible?

    Best Regards.

     public class InitiatesController : ApiController
        {
            private readonly EPINMiddleWareAPIContext context;
    
            
            public InitiatesController(EPINMiddleWareAPIContext context)
            {
                this.context = context;
            }
    
    
            // POST: api/Game
            //[RequireHttps] For Prod Only
            
            [HttpPost, Route("initiation")]
            public async Task<IHttpActionResult> PostInitiate(InitiateRequest initiate)
            {
    ...
    calling confirmation here programmatically
    }
    [HttpPost, Route("confirmation")]
    public async Task<IHttpActionResult> PostConfirmation(ConfirmRequest confirm)
    {
    ...
    }

    Monday, June 24, 2019 7:14 PM

All replies

  • User475983607 posted

    Actions are methods and can be called like any method. 

    [HttpPost, Route("initiation")]
    public async Task<IHttpActionResult> PostInitiate(InitiateRequest initiate)
    {
    	ConfirmRequest request = new ConfirmRequest();
    	return PostConfirmation(request);
    }
    [HttpPost, Route("confirmation")]
    public async Task<IHttpActionResult> PostConfirmation(ConfirmRequest confirm)
    {
     ...
    }

    IMHO, an odd design and you probably should refactor shared code into a private method within the controller or another class. 

    Anyway, are you receiving an error?

    Monday, June 24, 2019 9:00 PM
  • User61956409 posted

    Hi cenk1536,

    cenk1536

    I would like to call confirmation inside of initiation

    As mgebhard mentioned, you can extract and refactor shared code into a private method, like below. 

            [HttpPost, Route("initiation")]
            public async Task<IHttpActionResult> PostInitiate(InitiateRequest initiate)
            {
                //...
    
                //calling confirmation here programmatically
    
                //code logic here
    
                var confirmRequest = new ConfirmRequest();
                return ConfirmFunc(confirmRequest);
            }
    
            [HttpPost, Route("confirmation")]
            public async Task<IHttpActionResult> PostConfirmation(ConfirmRequest confirm)
            {
                return ConfirmFunc(confirm);
            }
    
            private IHttpActionResult ConfirmFunc(ConfirmRequest confirm)
            {
                //...
                //code logic here
            }

    With Regards,

    Fei Han

    Tuesday, June 25, 2019 3:01 AM
  • User-1104215994 posted

    It is getting messy, now the challenge is not returning IHttpActionResult from the initiation method. If I omit return type from initiation, how can I check model state and return bad request and more importantly I am calling 3rd party rest API inside of this <g data-gr-id="366" id="366" class="gr_ gr_366 gr-alert gr_gramm Punctuation multiReplace">initiation.</g> If 3rd party returns bad request or unauthorized etc. how can I show it to the client?

    Tuesday, June 25, 2019 6:41 AM
  • User475983607 posted

    It is getting messy, now the challenge is not returning IHttpActionResult from the initiation method. If I omit return type from initiation, how can I check model state and return bad request and more importantly I am calling 3rd party rest API inside of this initiation. 

    What is an "initiation method" and what does and "initiation method" have to do with IHttpActionResults? 

    Model state is a part of the model binding process where a client sends data to an Action.  If you are passing arguments to another method then it is up to you to validate the data.  Use TryValidateModel or ValidateModel to invoke all model validators. 

    https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controllerbase.tryvalidatemodel?view=aspnetcore-2.2

    If 3rd party returns bad request or unauthorized etc. how can I show it to the client?

    Well, your code checks for a 400 (Bad Request) from the remote service.   Write logic to to handle the 400 and return a message to the client.  What that message looks like and how the client display the message is determined by your design and application requirements. 

    Can you explain the message format, share the client code, and explain the problem?

    Tuesday, June 25, 2019 10:50 AM
  • User-1104215994 posted

    Hi <g class="gr_ gr_26 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace" id="26" data-gr-id="26">mgebhard</g>,

    Long story short, as I posted many times :) I have an asp.net web API. It has 2 action methods; initiation and confirmation. In those methods, I am calling 3rd party rest API and returning the response to the client. Thank God it is working even though it is legacy. (Trying to refactor it is <g class="gr_ gr_30 gr-alert gr_gramm gr_hide gr_inline_cards gr_run_anim Grammar multiReplace replaceWithoutSep replaceWithoutSep" id="30" data-gr-id="30">another posts subject</g>)

    The logic behind these services is that,

    1. Client first calls initiation to start buying online game codes. Sending game code, quantity, etc.
    2. The 3rd party sends back a response saying if there is a game (price, unique id) or not, etc.
    3. Then the client has to call the confirmation method in order to complete this purchase. Sending this unique id to the confirmation.
    4. The 3rd party sends back a response with the game codes.

    Problem is the client doesn't want to make 2 calls (initiation and confirmation). They want to call initiation and get back the game codes. That's why I am trying to find a workaround for this new request.

    Tuesday, June 25, 2019 11:34 AM
  • User753101303 posted

    Hi,

    Or you could create your own "facade" that will chain those two calls behind the scene. It still seems a bit weird. The first one seems basically to handle a shopping cart allowing to add/remove games etc... as you go while the other one seems to be about ordering the whole shopping cart ?

    How one could check what he is about to order or they don't want a shopping cart and that each game can be ordered immediately as you go ?

    Tuesday, June 25, 2019 11:48 AM
  • User-1104215994 posted

    Hi <g class="gr_ gr_12 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace" id="12" data-gr-id="12">PatriceSc</g>,

    Initiation reserves the game and confirmation <g class="gr_ gr_37 gr-alert gr_gramm gr_inline_cards gr_run_anim Grammar multiReplace" id="37" data-gr-id="37">completes</g> the purchase. If I just call <g class="gr_ gr_63 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace" id="63" data-gr-id="63">initiaiton</g> and don't call the confirmation with the unique id, this game is not purchased. Can you show me an <g class="gr_ gr_265 gr-alert gr_gramm gr_inline_cards gr_run_anim Grammar only-ins replaceWithoutSep" id="265" data-gr-id="265">example</g> how to create my own facade? I mean I am confused and need help.

    Tuesday, June 25, 2019 2:17 PM
  • User475983607 posted

    cenk1536

    Initiation reserves the game and confirmation completes the purchase. If I just call initiaiton and don't call the confirmation with the unique id, this game is not purchased. Can you show me an example how to create my own facade? I mean I am confused and need help.

    The Facade Pattern is very well documented. There's a lot of information that a simple Google search will uncover. 

    https://en.wikipedia.org/wiki/Facade_pattern

    Basically, the Facade Pattern hides complex logic behind a simpler interface.  Web API or any service is an example of a Facade Pattern.

    Keep in mind you are asking question as if we understand your code and business requirements.  Frankly, I do not understand how it's possible to accomplish this task in one request.  It seems the user selects a game code, then purchases the game code.  That's always two steps.  One step to GET the information to the screen (or client) and another step to make a purchase (POST) using the information provided. 

    If the purchase process contains two steps, initialize and confirmation, then it seems the initialization step should be part of the GET step not the purchase step.  Or the 3rd party service limits the process in some unknown way.

    Tuesday, June 25, 2019 2:57 PM
  • User-1104215994 posted

    If the purchase process contains two steps, initialize and confirmation, then it seems the initialization step should be part of the GET step not the purchase step.  Or the 3rd party service limits the process in some unknown way.

    Yes, the 3rd party makes me call initiation and confirmation with post requests in order to complete the process. Basically, both methods have the same request values. Somehow, I have to call this initiation and make some validation (if requested quantity of games is in the stock) I should call the confirmation method and finally return the response to the client.

    Tuesday, June 25, 2019 5:42 PM
  • User475983607 posted

    Yes, the 3rd party makes me call initiation and confirmation with post requests in order to complete the process. Basically, both methods have the same request values. Somehow, I have to call this initiation and make some validation (if requested quantity of games is in the stock) I should call the confirmation method and finally return the response to the client.

    Please do not make the community guess. 

    Can you explain why you are unable to invoke a remote Initiation request and a remote Confirmation request in a single Web API request?  Is there a physical limitation where the user must select something?  Can you explain clearly the problem and any errors you are receiving?

    Tuesday, June 25, 2019 5:49 PM
  • User-1104215994 posted

    I couldn't visualize the solution in my mind. I added 2 class libraries into my solution for DAL and Bussiness Model. In the Business model, I added a gameDTO, a gamePurchaseRequest (adding some data and insert into a table)  and gamePurchaseResponse (inserting a response from 3rd party service into a table) entities. For the time being there is only one repository so do I need generic repo? (I don't think so) Since I will use add, update, query do I need to use transactions?

    Tuesday, June 25, 2019 6:55 PM
  • User475983607 posted

    I couldn't visualize the solution in my mind. I added 2 class libraries into my solution for DAL and Bussiness Model. In the Business model, I added a gameDTO, a gamePurchaseRequest (adding some data and insert into a table)  and gamePurchaseResponse (inserting a response from 3rd party service into a table) entities. For the time being there is only one repository so do I need generic repo? (I don't think so) Since I will use add, update, query do I need to use transactions?

    As far as I can tell, your response has nothing to do with the problem.  A repository is an abstraction between business logic and the database.  Since EF is already a repository you created an extra layer perhaps to replace EF with another ORM in the future.  Either way, the repository and EF are not related to the problem. 

    Is it physically possible to invoke the remote Initiation request and the remote Confirmation request in a single Web API request? Or is it not possible because the user must do something like make a selection?  If it is possible then all you have to do is list the steps involved to complete the process then write the code.  

    Tuesday, June 25, 2019 7:41 PM