locked
Getting Query Parameters in the Controller within an HTTPGet RRS feed

  • Question

  • User-868767480 posted

    Morning,

    I'm trying to write an HTTPGet method which retrieves the parameters being passed to it during the web call.  In the second code set below you can see I'm using uribuilder to build the uri which contains 1 or more parameters.  How do i get these parameters in the HTTPGet method in the controller?

    Second question, i want to make my HTTPGet flexible enough to where i don't have to pass any parameters, do i have to create two HTTPGet methods in my controller?

    Thanks in advance

    Madaxe

    //https://localhost:44337/api/FileTransfer/PostDocument
            [HttpGet]
            public IHttpActionResult GetDocumentProps()
            {
                //
                // TODO
                //
                return Ok();
            }
    private async static Task<UsersRoot> GetDocAttr ()
            {
                SimpleLog.WriteEventLog("GetDocAttr - Start.");
                UsersRoot ReturnUsersRoot = null;
                try
                {
                    using (HttpClient httpClient = new HttpClient())
                    {
                        httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
                        httpClient.DefaultRequestHeaders.Add("Authorization", _APIKey);
    
                        UriBuilder builder = new UriBuilder("https://api.lekolabs.com/v2/");
                        var query = HttpUtility.ParseQueryString(builder.Query);
                        query["classid"] = "1";
    query["partid"] = "lux34561";
    query["documentcoreobjectid"] = "13456756"; builder.Query = query.ToString();
    using (HttpResponseMessage HttpResponseMessage = await httpClient.GetAsync(builder.ToString())) { if (HttpResponseMessage.StatusCode == System.Net.HttpStatusCode.OK) { using (HttpContent HttpContent = HttpResponseMessage.Content) { string MyContent = await HttpContent.ReadAsStringAsync(); ReturnUsersRoot = XMLHelper.DeserializeObject<UsersRoot>(MyContent); } } } } SimpleLog.WriteEventLog("GetDocAttr - End."); } catch (Exception ex) { //die quietly. SimpleLog.WriteEventLog("GetDocAttr - Exception Raised - " + ex.ToString()); } return ReturnUsersRoot; }

    Friday, December 6, 2019 6:37 AM

Answers

All replies

  • User1120430333 posted

    I'm trying to write an HTTPGet method which retrieves the parameters being passed to it during the web call. In the second code set below you can see I'm using uribuilder to build the uri which contains 1 or more parameters. How do i get these parameters in the HTTPGet method in the controller?

    You can use a custom object like a DTO and pass multiple parms using a DTO, which is using Encapsulation, becuase otherwise, you would have to string out the parms on the URL itself that can be problematic. If you are only passing one parm's data in the DTO and the other properties properties of the DTO for other parms are not used, then that's OK, becuase the custom object's content is hidden inside the object. So it doesn't matter if you are passing one parm's data  or multiple parms of data in the custom class, because the custom object is viewed as a whole no matter what.

    <copied>

    In object-oriented programming (OOP), encapsulation refers to the bundling of data with the methods that operate on that data, or the restricting of direct access to some of an object's components.

    <end>

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

    Below you see the concept of a DTO being used as a parm on an action method that was sent by the WebAPI client, becuase otherwise,  I would have to formulate a URL that addressed those 3 parms being strung out on the URL. So what that I only put some data in FirstName property and left the other two blank or not used, becuase the DTO is being viewed as a whole that is being sent, as an example?   

    So if you sent the parm data for LastName and it had O'Mally as the data being sent as a parm on the URL, then you will get a malformed URL error, becuase of the quote being used in the data passed on the URL. But if one uses the DTO and its LastName property, then you can pass O'Mally, because the DTO/custom object with Encapsulation being used hides the data and it can't be seen being passed on the URL.

    HttpPost]
            [Route("Add")]
            public async Task Add(DtoAuthor dto)
            {
                 await dao.Add(dto);
            }
    public void Add(DtoAuthor dto)
            {
                using (var client = new HttpClient { BaseAddress = new Uri("http://localhost") })
                {
                    string serailizeddto = JsonConvert.SerializeObject(dto);
    
                    var inputMessage = new HttpRequestMessage
                    {
                        Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                    };
    
                    inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    HttpResponseMessage message =
                        client.PostAsync("WebAPI/api/author/Add", inputMessage.Content).Result;
    
                    if (!message.IsSuccessStatusCode)
                        throw new Exception(message.ToString());
                }
            }
    namespace Entities
    {
        public class DtoAuthor
        {
            public int AuthorId { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
        }
    }
    


    Here is another example of sending the DTO as a parm.  I changed the method in this post to show  a DTO being sent as a parm.


            public DtoAuthor  Find(ParmDto parmdto)
            {
                DtoAuthor dto;
    
                using (var client = new HttpClient())
                {
                    var uri = new Uri("http://localhost/WebAPI/api/author/Find?parmdto=" + parmdto);
                    HttpResponseMessage getResponseMessage = client.GetAsync(uri).Result;
    
                    if (!getResponseMessage.IsSuccessStatusCode)
                        throw new Exception(getResponseMessage.ToString());
    
                    var responsemessage = getResponseMessage.Content.ReadAsStringAsync().Result;
    
                    dynamic author = JsonConvert.DeserializeObject(responsemessage);
    
                    dto = author.ToObject<DtoAuthor>();
                }
    
                return dto;
            }

    Friday, December 6, 2019 8:44 AM
  • User-868767480 posted

    Thanks for the reply,

    So i noticed you used PostAsync instead of GetAsync, why and whats the difference?

    Thanks

    Madaxe

    Saturday, December 7, 2019 11:33 AM
  • User1120430333 posted

    Thanks for the reply,

    So i noticed you used PostAsync instead of GetAsync, why and whats the difference?

    Thanks

    Madaxe

    In the example that I have shown, it is one of several methods working with a WebAPI that is doing CRUD operation with the database using DAO(s) in the data access layer doing CRUD with the database using the ADO.NET Entity Framework.

    https://www.codeproject.com/Articles/1050468/Data-Transfer-Object-Design-Pattern-in-Csharp

    https://docs.microsoft.com/en-us/aspnet/web-api/overview/data/using-web-api-with-entity-framework/part-5

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

    https://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm

    Example...…...

    using System;
    using System.Collections.Generic;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Text;
    using Entities;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    
    namespace ServiceLayer
    {
        public class AuthorSvc :IAuthorSvc
        {
            public List<DtoAuthor> GetAll()
            {
                var dtoauthors = new List<DtoAuthor>();
    
                using (var client = new HttpClient())
                {
                    var uri = new Uri("http://localhost/WebAPI/api/author/GetAll");
    
                    var response = client.GetAsync(uri).Result;
    
                    if (!response.IsSuccessStatusCode)
                        throw new Exception(response.ToString());
    
                    var responseContent = response.Content;
                    var responseString = responseContent.ReadAsStringAsync().Result;
    
                    dynamic authors = JArray.Parse(responseString) as JArray;
    
                    foreach (var obj in authors)
                    {
                        DtoAuthor dto = obj.ToObject<DtoAuthor>();
    
                        dtoauthors.Add(dto);
                    }
                }
    
                return dtoauthors;
            }
            public List<DtoAuthorType> GetAuthorTypes()
            {
                var dtoauthortypes = new List<DtoAuthorType>();
    
                using (var client = new HttpClient())
                {
                    var uri = new Uri("http://localhost/WebAPI/api/author/GetAuthorTypes");
    
                    var response = client.GetAsync(uri).Result;
    
                    if (!response.IsSuccessStatusCode)
                        throw new Exception(response.ToString());
    
                    var responseContent = response.Content;
                    var responseString = responseContent.ReadAsStringAsync().Result;
    
                    dynamic authortypes = JArray.Parse(responseString) as JArray;
    
                    foreach (var obj in authortypes)
                    {
                        DtoAuthorType dto = obj.ToObject<DtoAuthorType>();
    
                        dtoauthortypes.Add(dto);
                    }
                }
    
                return dtoauthortypes;
            }
    
            public DtoAuthor  Find(int id)
            {
                DtoAuthor dto;
    
                using (var client = new HttpClient())
                {
                    var uri = new Uri("http://localhost/WebAPI/api/author/Find?id=" + id);
                    HttpResponseMessage getResponseMessage = client.GetAsync(uri).Result;
    
                    if (!getResponseMessage.IsSuccessStatusCode)
                        throw new Exception(getResponseMessage.ToString());
    
                    var responsemessage = getResponseMessage.Content.ReadAsStringAsync().Result;
    
                    dynamic author = JsonConvert.DeserializeObject(responsemessage);
    
                    dto = author.ToObject<DtoAuthor>();
                }
    
                return dto;
            }
    
            public void Add(DtoAuthor dto)
            {
                using (var client = new HttpClient { BaseAddress = new Uri("http://localhost") })
                {
                    string serailizeddto = JsonConvert.SerializeObject(dto);
    
                    var inputMessage = new HttpRequestMessage
                    {
                        Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                    };
    
                    inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    HttpResponseMessage message =
                        client.PostAsync("WebAPI/api/author/Add", inputMessage.Content).Result;
    
                    if (!message.IsSuccessStatusCode)
                        throw new Exception(message.ToString());
                }
            }
    
            public void Update(DtoAuthor dto)
            {
                using (var client = new HttpClient { BaseAddress = new Uri("http://localhost") })
                {
                    string serailizeddto = JsonConvert.SerializeObject(dto);
    
                    var inputMessage = new HttpRequestMessage
                    {
                        Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                    };
    
                    inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    HttpResponseMessage message =
                        client.PostAsync("WebAPI/api/author/Update", inputMessage.Content).Result;
    
                    if (!message.IsSuccessStatusCode)
                        throw new Exception(message.ToString());
                }
            }
    
            public void Delete(DtoId dto)
            {
                using (var client = new HttpClient { BaseAddress = new Uri("http://localhost") })
                {
                    string serailizeddto = JsonConvert.SerializeObject(dto);
    
                    var inputMessage = new HttpRequestMessage
                    {
                        Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                    };
    
                    inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                    HttpResponseMessage message =
                        client.PostAsync("WebAPI/api/author/Delete", inputMessage.Content).Result;
    
                    if (!message.IsSuccessStatusCode)
                        throw new Exception(message.ToString());
                }
            }
        }
    }
    
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    using Entities;
    using DAL;
    
    namespace WebAPI.Controllers
    {
        [Produces("application/json")]
        [Route("api/[controller]")]
        [ApiController]
        public class AuthorController : ControllerBase
        {
            private IDaoAuthor dao;
            public AuthorController(IDaoAuthor daoAuthor)
            {
                dao = daoAuthor;
            }
    
            [HttpGet]
            [Route("GetAll")]
            public async Task<List<DtoAuthor>> GetAll()
            {
                return  await dao.GetAll();
            }
    
            [HttpGet]
            [Route("GetAuthorTypes")]
            public async Task<List<DtoAuthorType>> GetAuthorTypes()
            {
                return await dao.GetAuthorTypes();
            }
    
            [HttpGet]
            [Route("Find")]
            public async Task<DtoAuthor> Find(int id)
            {
                return await dao.Find(id);
            }
    
            [HttpPost]
            [Route("Add")]
            public async Task Add(DtoAuthor dto)
            {
                 await dao.Add(dto);
            }
    
            [HttpPost]
            [Route("Update")]
            public async Task Update(DtoAuthor dto)
            {
                await dao.Update(dto);
            }
    
            [HttpPost]
            [Route("Delete")]
            public async Task Delete(DtoId dto)
            {
                await dao.Delete(dto.Id);
            }
        }
    }
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Entities;
    
    namespace DAL
    {
        public interface IDaoAuthor
        {
            Task<List<DtoAuthor>> GetAll();
            Task<DtoAuthor> Find(int id);
            Task<List<DtoAuthorType>> GetAuthorTypes();
            Task Add(DtoAuthor dto);
            Task Update(DtoAuthor dto);
            Task  Delete(int id);
        }
    }
    
    ========================================================================
    
    using System;
    using System.Collections.Generic;
    using System.Data.SqlClient;
    using System.Linq;
    using System.Threading.Tasks;
    using DAL.Models;
    using Entities;
    using Microsoft.EntityFrameworkCore;
    
    namespace DAL
    {
        public class DaoAuthor : IDaoAuthor
        {
            private PublishingCompanyContext pc;
    
            public DaoAuthor(PublishingCompanyContext dbcontext)
            {
                pc = dbcontext;
            }
    
            public async Task<List<DtoAuthor>> GetAll()
            {
                var dtos = new List<DtoAuthor>();
    
                var authors =  await pc.Author.ToListAsync();
    
                dtos.AddRange(authors.Select(author => new DtoAuthor()
                {
                    AuthorId = author.AuthorId,
                    FirstName = author.FirstName,
                    LastName = author.LastName
                }).ToList());
    
                return dtos;
            }
    
            public async Task<DtoAuthor> Find(int id)
            {
                var dto = new DtoAuthor();
    
                var author =  await pc.Author.FindAsync(id);
    
                if (author != null)
                {
                    dto.AuthorId = author.AuthorId;
                    dto.FirstName = author.FirstName;
                    dto.LastName = author.LastName;
                }
                else
                {
                    throw new Exception($"Author with ID = {id} was not found.");
                }
    
                return dto;
    
            }
            public async Task <List<DtoAuthorType>> GetAuthorTypes()
            {
                var dtos = new List<DtoAuthorType>();
    
                var authors = await pc.Author.ToListAsync();
    
                foreach (var author in authors)
                {
                    DtoAuthorType dto = new DtoAuthorType
                    {
                        AuthorId = author.AuthorId,
                        Value = author.AuthorId.ToString(),
                        Text = author.LastName + ", " + author.FirstName
                    };
    
                    dtos.Add(dto);
                }
    
                return dtos;
            }
            public async Task Add(DtoAuthor dto)
            {
                var author = new Author
                {
                    FirstName = dto.FirstName,
                    LastName = dto.LastName
                };
    
                pc.Author.Add(author);
                await pc.SaveChangesAsync();
    
            }
            public async Task Update(DtoAuthor dto)
            {
                var author = new Author
                {
                    AuthorId = dto.AuthorId,
                    FirstName = dto.FirstName,
                    LastName = dto.LastName
                };
    
                pc.Entry(author).State = EntityState.Modified;
                await pc.SaveChangesAsync();
    
            }
    
            public async Task Delete(int id)
            {
                
                var author = pc.Author.Find(id);
    
                if (author != null)
                {
                    var articles = await pc.Article.Where(a => a.AuthorId.ToString().Contains(id.ToString())).ToListAsync();
              
                    foreach (var article in articles)
                    {
                        author.Articles.Remove(article);
                    }
    
                    var payrolls = await pc.Payroll.Where(a => a.AuthorId.ToString().Contains(id.ToString())).ToListAsync();
    
                    foreach (var payroll in payrolls)
                    {
                        author.Payrolls.Remove(payroll);
                    }
    
                    pc.Author.Remove(author);
                    await pc.SaveChangesAsync();
                }
    
            }
    
        }
    }
    

    Saturday, December 7, 2019 2:03 PM
  • User475983607 posted

    So i noticed you used PostAsync instead of GetAsync, why and whats the difference?

    HTTP Get uses the URL to submit data.  HTTP Post uses the message body to submit data.

    https://www.w3schools.com/tags/ref_httpmethods.asp

    How do i get these parameters in the HTTPGet method in the controller?

    Define input parameters in the action method that matches the URL querystring name or route.  This is a fundamental concept that is covered in every beginning level Web API tutorial.  I recommend reading the official documentation to learn the basics.

    https://docs.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api

    Second question, i want to make my HTTPGet flexible enough to where i don't have to pass any parameters, do i have to create two HTTPGet methods in my controller?

    This second requirements does not make sense.  Saving or updating records requires data to pass from the client to the server.  The get to design a solution that uses an HTTP GET, HTTP POST, or HTTP PUT to accomplish this.  Reading the docs will help.

    Saturday, December 7, 2019 3:18 PM
  • User-868767480 posted

    Thanks for all the fantastic info,

    This is what I have from all the information any feed back would be great.

    I do have one last question how do i implement awaitable on my class?

    Really Appreciated

    Madaxe

    WebAPIConfig.cs
    config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional }
    );
    config.Formatters.XmlFormatter.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("multipart/form-data"));

    Entry.cs
    
    public class Class1
        {
            static void Main(string[] args)
            {
                // Display the number of command line arguments.
                ClientSideDTOImpl clientSideDTOImpl = new ClientSideDTOImpl();
    
                IDTO NullDTO=null;
                Task<IDTO> ReturnValue = clientSideDTOImpl.WithNullDTO(NullDTO);
    
                IDTO NewDTO = new DTO();
                NewDTO.IsUsed = true;
                NewDTO.PartID = "washere";
                NewDTO.ObjectID = 123456;
                Task<IDTO> ReturnValue2 = clientSideDTOImpl.WithNewDTO(NewDTO);
            }
        }
    ClientSideImpl.cs
    
    public class ClientSideDTOImpl
        {
            public async Task<IDTO> WithNullDTO(IDTO NUllDTO)
            {
                IDTO ReturnDTO = null;
    
                try
                {
                    using (var client = new HttpClient { BaseAddress = new Uri("https://localhost:44349/") })
                    {
                        string serailizeddto = JsonConvert.SerializeObject(NUllDTO);
    
                        var inputMessage = new HttpRequestMessage
                        {
                            Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                        };
    
                        inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                        HttpResponseMessage message =
                            client.PostAsync("api/DataTransferObject/Thingy1", inputMessage.Content).Result;
    
                        if (message.IsSuccessStatusCode)
                        {
                            string result = message.Content.ReadAsStringAsync().Result;
                            ReturnDTO = JsonConvert.DeserializeObject<DTO>(result);
                        }
                        else
                        {
                            throw new Exception(message.ToString());
                        }
                    }
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex);
                }
                return ReturnDTO;
            }
            public async Task<IDTO> WithNewDTO(IDTO NewDTO)
            {
                IDTO ReturnDTO = null;
    
                try
                {
                    using (var client = new HttpClient { BaseAddress = new Uri("https://localhost:44349/") })
                    {
                        string serailizeddto = JsonConvert.SerializeObject(NewDTO);
    
                        var inputMessage = new HttpRequestMessage
                        {
                            Content = new StringContent(serailizeddto, Encoding.UTF8, "application/json")
                        };
    
                        inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    
                        HttpResponseMessage message =
                            client.PostAsync("api/DataTransferObject/Thingy1", inputMessage.Content).Result;
    
                        if (message.IsSuccessStatusCode)
                        {
                            string result = message.Content.ReadAsStringAsync().Result;
                            ReturnDTO = JsonConvert.DeserializeObject<DTO>(result);
                        }
                        else
                        {
                            throw new Exception(message.ToString());
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
                return ReturnDTO;
            }
    
        }
    DataTransferObjectController.cs
    
    public class DataTransferObjectController : ApiController
        {
    
            private IServerSideDTOImpl _ServerSideDTOImpl = null;
    
            public DataTransferObjectController(IServerSideDTOImpl iServerSideDTOImpl)
            {
                this._ServerSideDTOImpl = iServerSideDTOImpl;
            }
    
            [HttpPost]
            public async Task<IHttpActionResult> Thingy1([FromBody]JObject data)
            {
                IDTO NewDTO = null;
                if (data != null)
                {
                    if (data["IsUsed"].ToObject<Boolean>() == true)
                    {
                        NewDTO = this._ServerSideDTOImpl.GetData();
                    }
                }
                return Ok(NewDTO);
            }
        }
    ServerSideImpl.cs
    public class ServerSideDTOImpl : IServerSideDTOImpl { public IDTO GetData() { IDTO ReturnDTO = new DTO(); ReturnDTO.IsUsed = false; ReturnDTO.PartID = "now im here"; ReturnDTO.ObjectID = 654321; return ReturnDTO; } }
    DefaultRegistry.cs (Dependency Injection)
    
    For<IServerSideDTOImpl>().Use<ServerSideDTOImpl>();

    Sunday, December 8, 2019 12:37 PM
  • User475983607 posted

    madaxe

    This is what I have from all the information any feed back would be great.

    Have you tried executing the code?  As written I expect the code to throw exceptions.  

    The DI service makes no logical sense.  Can you explain the design approach?

    I would fail this in a code review and recommend using the actual type in the action signature and let the model binder populate the type.  Same idea with the return type.

            [HttpPost]
            public async Task<IHttpActionResult> Thingy1([FromBody]TheActualType data)
            {

    The HttpClient is designed for use in ab entire application. The way you are using HttpClient can cause port exhaustion. 

    https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/console-webapiclient

    madaxe

    I do have one last question how do i implement awaitable on my class?

    See the previous link.

    It seems like you are not reading the official documentation.

    Sunday, December 8, 2019 1:06 PM
  • User-868767480 posted

    No the code works fine i can send a DTO and receive one back, it does what i want it to do with no issues.

    In my solution I have a Word integration with a registration JSON file. When the user does something i send the current registration file to the web-server, complete the server side actions and send back a JSON file so that the client side code can do any updates changes.

    So what I posted works for my use-case, obviously i did not include the database portion in the server side implementation.

    The only sticking point was I get a warning about the missing await, hence my last post

    Thanks

    Madaxe

    Sunday, December 8, 2019 2:28 PM
  • User475983607 posted

    madaxe

    The only sticking point was I get a warning about the missing await, hence my last post

    Invoke the async task from main.

    YourMethod().GetAwaiter().GetResult();

    https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Sunday, December 8, 2019 3:16 PM