locked
HTTPClient usage RRS feed

  • Question

  • User-1104215994 posted

    Hi there,

    I have a solution which has business service, business entities, data model layers, and an asp.net <g data-gr-id="295" id="295" class="gr_ gr_295 gr-alert gr_spell ContextualSpelling ins-del multiReplace">web</g> API project. I am calling 3rd party web <g class="gr_ gr_221 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace" id="221" data-gr-id="221">api</g> in my business service layer. I would like to know what is the proper way to use <g class="gr_ gr_369 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace" id="369" data-gr-id="369"><g class="gr_ gr_390 gr-alert gr_gramm gr_inline_cards gr_run_anim Grammar only-ins doubleReplace replaceWithoutSep" id="390" data-gr-id="390">http</g></g> client?

    Here is my controller action:

    [System.Web.Http.RoutePrefix("api/v2/game")]
        public class GameController : ApiController
        {
            private readonly IGameServices _gameServices;
           
    
            #region Public Constructor  
    
            /// <summary>  
            /// Public constructor to initialize game service instance  
            /// </summary>  
            public GameController(IGameServices gameServices)
            {
                _gameServices = gameServices;
            }
    
            
            #endregion
    
    
            // POST: api/Game
            //[RequireHttps] For Prod Only
    
            [HttpPost, Route("purchase")]
            public async Task<IHttpActionResult> PurchaseGame(RequestDto game)
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(ModelState);
                }
                
                var gameConfirmResponse = await _gameServices.GamePurchase(game);
    
                return Ok(gameConfirmResponse);
            }
    
            
    
           protected override void Dispose(bool disposing)
            {
                if (disposing)
                {
                    //unitOfWork.Dispose();
                }
                base.Dispose(disposing);
            }
        }

    Here is my business service:

    public class GameServices : IGameServices
        {
            private readonly UnitOfWork _unitOfWork;
    
            /// <summary>
            /// Public constructor.
            /// </summary>
            public GameServices(UnitOfWork unitOfWork)
            {
                _unitOfWork = unitOfWork;
            }
            
            /// <summary>
            /// Creates a product
            /// </summary>
            /// <param name="requestDto"></param>
            /// <returns></returns>
            public async Task<GameConfirmResponse> GamePurchase(RequestDto requestDto)
            {
                using (var scope = new TransactionScope())
                {
    
                    //Transform DTO into GameRequest for calling Razer Initiate
                    var config = new MapperConfiguration(cfg => {
                        cfg.CreateMap<RequestDto, GameRequest>();
                    });
                    var iMapper = config.CreateMapper();
                    var gameRequest = iMapper.Map<RequestDto, GameRequest>(requestDto);
                    //Create signature
                    gameRequest = Utilities.CreateSignature(gameRequest, RequestType.Initiate);
                    //Unique reference ID
                    gameRequest.referenceId = Guid.NewGuid().ToString();
                    try
                    {
                        //Add request into database
                        _unitOfWork.GameRepository.Insert(gameRequest);
                        
                    }
                    catch (Exception e)
                    {
                        
                        throw e;
                    }
                    
    
                    #region Call Razer initiate
    
                    HttpResponseMessage response = null;
                    try
                    {
                        response = await Utilities.CallRazer(gameRequest, "purchaseinitiation");
                    }
                    catch (Exception e)
                    {
                       
                        throw e;
                    }
                   
                    //Read response
                    var htmlResponse = await response.Content.ReadAsStringAsync();
    
                    var gameResponse = JsonConvert.DeserializeObject<GameResponse>(htmlResponse);
                    //Adding response into database
                    _unitOfWork.GameResponseRepository.Insert(gameResponse);
                    
                    if (gameResponse.initiationResultCode == "00")
                    {
                        //Create signature
                        var gameConfirmRequest = Utilities.CreateSignature(gameRequest, RequestType.Confirm);
                    }
                    #endregion
                    await _unitOfWork.SaveAsync();
    
                    var gameConfirmResponse = Mapper.Map<RequestDto, GameConfirmResponse>(requestDto);
                    scope.Complete();
                    
                    return gameConfirmResponse;
                }
            }
    
            
            public enum RequestType
            {
                Initiate = 0,
                Confirm = 1
                
            }
    
        }

    Here is the CallRazer:

    public class Utilities
        {
            private static HttpClient httpClient = new HttpClient();
            
    
            public static async Task<HttpResponseMessage> CallRazer(GameRequest gameRequest, string url)
            {
                //var httpClient = new HttpClient();
    
                //Convert request
                var keyValues = gameRequest.ToKeyValue();
                var content = new FormUrlEncodedContent(keyValues);
    
                //Call Game
                var response = await httpClient.PostAsync("https://test.com/purchaseinitiation", content);
                return response;
            }
        }

    Tuesday, July 2, 2019 5:16 AM

All replies

  • User475983607 posted

    This thread is very similar to your others.  Rather than solving the problem you are throwing design patterns and code at a basic logic problem that does not need all the extra layers and complexity.  At the same time, you are not using the patterns and API correctly.

    I recommend now, as I did in your other threads, to take advantage of  the IoC container you selected for this project; Unity.  It makes little sense to craft a custom solution when you can use Unity.   Either configure HttpClient as a Singleton or build a factory.  You will need to study the Unity documentation or do a Google search for tips and code.

    https://stackoverflow.com/questions/44912474/using-unity-to-create-a-singleton-that-is-used-in-my-class

    If you want to roll your own and manage scope yourself, then look into the Singleton pattern.  Still I recommend using the IoC container you selected for this project.

    https://csharpindepth.com/articles/singleton

    Tuesday, July 2, 2019 11:37 AM
  • User-1104215994 posted

    Hi <g class="gr_ gr_5 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace" id="5" data-gr-id="5">mgeebhard</g>,

    I followed the link you provided. I added an IUtilities interface and changed the code as follows. But unfortunately, it doesn't work. <g class="gr_ gr_250 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace" id="250" data-gr-id="250">httpclient</g> is null.

    public class Utilities : IUtilities
        {
            private static HttpClient _httpClient;
    
            public Utilities(HttpClient httpClient)
            {
                _httpClient = httpClient;
            }
    
    
            public static async Task<HttpResponseMessage> CallRazer(GameRequest gameRequest, string url)
            {
                
                //Convert request
                var keyValues = gameRequest.ToKeyValue();
                var content = new FormUrlEncodedContent(keyValues);
    
                //Call Game Sultan
                var response = await _httpClient.PostAsync("https://test.com/"+url, content);
                return response;
            }
        }
        
        }

    Here is <g class="gr_ gr_279 gr-alert gr_gramm gr_inline_cards gr_run_anim Grammar only-ins replaceWithoutSep" id="279" data-gr-id="279">Unity</g> config:

    public static void RegisterTypes(IUnityContainer container)
            {
                // NOTE: To load from web.config uncomment the line below.
                // Make sure to add a Unity.Configuration to the using statements.
                // container.LoadConfiguration();
    
                // TODO: Register your type's mappings here.
                // container.RegisterType<IProductRepository, ProductRepository>();
                container.RegisterType<IGameServices, GameServices>().RegisterType<UnitOfWork>(new HierarchicalLifetimeManager());
                container.RegisterType<IUtilities, Utilities>(new ContainerControlledLifetimeManager());
                container.RegisterType<HttpClient, HttpClient>(new ContainerControlledLifetimeManager(), new InjectionConstructor());
            }

    Tuesday, July 2, 2019 12:46 PM
  • User475983607 posted

    cenk1536

    I followed the link you provided. I added an IUtilities interface and changed the code as follows. But unfortunately, it doesn't work. httpclient is null.

    You are doing something wrong...  Simply looking at the code, I question the use of static members in a service designed for use in an IoC container.   I'm familiar with DI that comes with ASP.NET Core but have little to no experience with Unity.  Can you explain the design and reasoning behind the design?

    Perhaps you need to set aside time to learn the IoC container you selected for this project?

    Tuesday, July 2, 2019 1:00 PM