Use Same controller and method for managing two models

Binumon George 161 Reputation points
2023-01-18T11:35:45.0766667+00:00

Hi All,

    In my .net core Web API application i want to use same controller and method for two models.

Consider two Models like Country and State. Giving below two different post request body

request body 1


 {
   DataType:"Country",
     Data: [
	{
        Id:1,
        Name: "CountryName1"
      },
      {
        Id:2,
        Name: "CountryName2"
      }
]}


Request Body 2

request body 2
{
   DataType:"State",
     Data: [
	{
        Id:1,
        Name: "StateName1",
        CountryId:2
      },
      {
        Id:2,
        Name: "StateName2"
        CountryId:1
      }
]}

My Controller


[Route("api/V1/[controller]")]
    [ApiController]
    public class AddDataController : ControllerBase
    {
        [HttpPost("Save")]
        public IActionResult SaveData ([FromBody] Data data)
        {
		if(data.DataType=="Country")
			{
			AddCountryDetails();
			}
			if(data.DataType=="State")
				{
					AddStateDetails();
				}
	  }
    }

My requirment is by using Single Url I want to add two Model data in Database. I can't consider as single model.

https://AbcUrl/api/v1/AddData/Save

Developer technologies ASP.NET ASP.NET Core
0 comments No comments
{count} votes

Accepted answer
  1. Anonymous
    2023-01-19T06:18:31.0533333+00:00

    Hi @Binumon George

    I assume the Country and State model as below:

        public class Country 
        { 
            public int CountryId { get; set; }
            public string CountryName { get; set; }
        }
        public class State
        { 
            public int StateId { get; set; }
            public string StateName { get; set; }
            public int CountryId { get; set; }
        }
    

    From your code the request body 1 and request body 2 only has one different property: CountryId, so, to receive the request body 1 and body 2, you can create a DataModel like this:

        public class DataModel
        {
            public string DataType { get; set; }
            public List<Datum> Data { get; set; }
        }
        public class Datum
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public int CountryId { get; set; }
        }
    

    Then, in the Controller, after receiving the Json data from the request body, you can use the Linq Select statement to query the data and convert the model to Country or State, code like this:

        [Route("api/[controller]")]
        [ApiController]
        public class AddDataController : ControllerBase
        {
            [HttpPost("Save")]
            public IActionResult SaveData([FromBody] DataModel data)
            {
                if (data.DataType=="Country")
                {
                    var countries = data.Data.Select(c=> new Country() { CountryId=c.Id, CountryName =c.Name}).ToList();
                    //insert countries into database.
    
                    return Ok(countries);
                }
                else if (data.DataType=="State")
                {
                    var states = data.Data.Select(c => new State() { StateId=c.Id, StateName =c.Name, CountryId = c.CountryId }).ToList();
                    //insert states into database.
                    return Ok(states); 
                }
                else
                {
                    return new JsonResult("DataType not match");
                }
            }
        }
    

    The result as below:

    If the request body is country:

    User's image

    If the request data is state:

    User's image


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,

    Dillion

    0 comments No comments

4 additional answers

Sort by: Most helpful
  1. AgaveJoe 30,126 Reputation points
    2023-01-18T13:27:58.6033333+00:00

    If I understand the question, you want to accept a single type and a collection of the same type. Update the action parameter to accept a collection; List<Data>. If the collection has one item in the list then there is a single item. The client will need to send a list as well.

    You have to understand that a single type and a collection, even of the same type, is a different type in C#. Anyway, this is a common situation and which is usually handled by passing a collection.


  2. AgaveJoe 30,126 Reputation points
    2023-01-18T17:10:24.6066667+00:00

    Oh I misunderstood, you need to use Generics, Reflection, and maybe a JSON library like Json.NET. You'll need to create an instance of the type Activator.CreateInstance Method. Then populate the instance from the data. The "Data" could be a List<object> or maybe a List<Dictionary>. You'll loop over the collection and populate the instance using reflection. You'll need to write custom validation logic to make sure the types (string, int, DateTime, etc.) match the instantiated type's property types.

    It's far easier to create two different controllers and let the model binder do its thing.

    I don't have time to write, test, and explain how to write reflection logic. But, there are a lot of online examples of how to write reflection logic and populate a type using reflection.

    0 comments No comments

  3. AgaveJoe 30,126 Reputation points
    2023-01-18T17:10:25.2966667+00:00

    Oh I misunderstood, you need to use Generics, Reflection, and maybe a JSON library like Json.NET. You'll need to create an instance of the type Activator.CreateInstance Method. Then populate the instance from the data. The "Data" could be a List<object> or maybe a List<Dictionary>. You'll loop over the collection and populate the instance using reflection. You'll need to write custom validation logic to make sure the types (string, int, DateTime, etc.) match the instantiated type.

    It's far easier to create two different controllers.

    I don't have time to write, test, and explain the code. But, there are a lot of online examples of how to write reflection logic and populate a type using reflection.

    0 comments No comments

  4. Bruce (SqlWork.com) 77,686 Reputation points Volunteer Moderator
    2023-01-18T19:10:03.6833333+00:00

    as request body 1 is a subset of request body 2, just convert request body 2 to classes to pass. you can check DataType property to know which type it is.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.