0

I am working on reading JSON data from the URL and insert it into the SQL table. I have used this sample URL https://raw.githubusercontent.com/wedeploy-examples/supermarket-web-example/master/products.json and create a Model class file as below.

View Model Class

public class ApiJsonViewModel
{
    public string Title { get; set; }
    public string Type { get; set; }
    public string Description { get; set; }
    public string Filename { get; set; }
    public string Height { get; set; }
    public string Width { get; set; }
    public string Price { get; set; }
    public string Rating { get; set; }
}

I have a form with one textbox control to display JSON key data from the third-party API URL and a drop-down list with values from the database.

The model class used to populate dropdownlist

     public class K360DbCatgViewModel

    {
        public string Name { get; set; }
        public string MetaTitle { get; set; }
        public string MetaKeywords { get; set; }
        public string MetaDescription { get; set; }      
        public string ShortDescription { get; set; }
        public string Description { get; set; }
        public string Specification { get; set; }
        public decimal Price { get; set; }
        public decimal? OldPrice { get; set; }
        public decimal? SpecialPrice { get; set; }
        public DateTimeOffset? SpecialPriceStart { get; set; }
        public DateTimeOffset? SpecialPriceEnd { get; set; }     
        public int StockQuantity { get; set; }
        public string Sku { get; set; }
        public string Gtin { get; set; }
        public string NormalizedName { get; set; }
        public int DisplayOrder { get; set; }     
        public int ReviewsCount { get; set; }
        public double? RatingAverage { get; set; }      
    }

Razor View Page

<table class="table" id="tb_properties" style="width:100%">
<tr>
    @if (ViewBag.ApiProp != null)
    {
        @foreach (var itemApiProp in ViewBag.ApiProp)
        {       
        <td>
            <input type="text" value="@itemApiProp.Key" class="form-control" />
        
                <select class="form-control">
                    <option value="">--Select-- </option>
                    @foreach (var itemK360Prop in ViewBag.K360Prop)
                    {
                    <option>@itemK360Prop.Key</option>
                    }
                </select>
        </td>
        
        }
    }
</tr>
<tr>
      <td> 
          <button type="submit" class="btn btn-primary" style="margin- 
          right:50px">Catalog Mapping</button>
     </td>
</tr>
</table>

Controller code to fetch values for the view controls

public IActionResult Index()
{
    string strAPIUrl = "https://raw.githubusercontent.com/wedeploy-examples/supermarket-web-example/master/products.json";
    string jsonUrlProducts;
    using (WebClient client = new WebClient())
    {
        jsonUrlProducts = client.DownloadString(strAPIUrl);
    }

    CreateDynamicAPiProp(jsonUrlProducts);
    CreateK360Prop();
    return View();
}

[HttpGet]
public IActionResult CreateDynamicAPiProp(string ApiUrl)
{
    Dictionary<string, object> dictResultsAdd = new Dictionary<string, object>();
    var objResponseB = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(ApiUrl);
    foreach (Dictionary<string, object> DictMainKV in objResponseB)
    {
        foreach (KeyValuePair<string, object> item in DictMainKV)
        {
            dictResultsAdd.Add(item.Key, item.Value);
        }

        break;
    }

    ViewBag.ApiProp = dictResultsAdd;
    return RedirectToAction("Index");
}

[HttpGet]
public IActionResult CreateK360Prop()
{
    var ListK360Prop = new List<ApiMapDbViewModel>();
    PropertyInfo[] propertyInfosK360 = typeof(K360DbCatgViewModel).GetProperties();
    foreach (PropertyInfo propertyInfoK360 in propertyInfosK360)
    {
        ListK360Prop.Add(new ApiMapDbViewModel{Value = propertyInfoK360.Name.ToString(), Key = propertyInfoK360.Name.ToString()});
    }

    ViewBag.K360Prop = ListK360Prop;
    return RedirectToAction("Index");
}

I have used the below jQuery and passed the JSON Model object to controller insert method on HTTP post to save selected records.

jQuery Code

@section scripts{ 
<script>
    $(function() {
        $("button[type='submit']").click(function() {
            event.preventDefault();
            var properties = [];
            $("#tb_properties tr:first").find("td").each(function(index, item) {
                var propertyname = $(item).find("input[type='text']").val();
                var selctedvalue = $(item).find("select").val();
                properties.push('"' + propertyname + '":"' + selctedvalue + '"');
            });
            var jsonstr = '{' + properties.join(",") + '}';
            var jsobject = JSON.parse(jsonstr);
            $.ajax({
                type: "Post",
                url: "/KEMap/Insert",
                data: {
                    jsonModel: jsobject
                },
                success: function(response) {
                    toastr.info(response.status + "<br>" + "<br>" + response.message);
                    $("#tb_properties select").val("");
                    $("#partial_div").load(window.location.href + " #partial_div");
                },
                error: function(xhr, textStatus, errorThrown) {
                    console.log('in error');
                }
            });

        });
    });
</script>

Insert Method

[HttpPost]
public IActionResult Insert(ApiJsonViewModel jsonModel)
{
    Type type = jsonModel.GetType();
    PropertyInfo[] props = type.GetProperties();
    List<K360mapMaster> K360mapListObj = new List<K360mapMaster>();
    K360mapListObj = props.Where(c => !string.IsNullOrEmpty(c.GetValue(jsonModel, null)?.ToString())).Select(c => new K360mapMaster()
    {ClientCatalog = c.Name, K360catalog = c.GetValue(jsonModel, null)?.ToString()}).ToList();
    if (K360mapListObj.Count > 0)
    {
        _context.K360mapMasters.AddRange(K360mapListObj);
        _context.SaveChanges();
        return Json(new { Status = "Sucess", Message = "Mapped" });
    }

    return Json(new { Status = "Fail", Message = "Not done" });
}

SQL Table

CREATE TABLE [dbo].[K360Map_Master](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ClientCatalog] [nvarchar](450) NOT NULL,
    [K360Catalog] [nvarchar](450) NOT NULL,
    [MapFlag] [bit] NOT NULL,
 CONSTRAINT [PK_K360Map_Master] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

Everything working fine. I was able to insert selected textbox and dropdown list values into the SQL table.

The problem is JSON data I am using from the third-party API URL differ dynamically. For example for the below 2 sample URLs, I need to create again 2 model class file.https://gist.githubusercontent.com/dpetersen/1237910/raw/6ceb2161f756d4b4d5c22754d1ed8d869249f186/product_grid.js https://raw.githubusercontent.com/mdn/fetch-examples/master/fetch-json/products.json.

I get the feedback as hardcoded coding with static data. I was not permitted to create a separate model class for each URL.

I also don't know how to proceed without creating a model class file. I need to pass selected control values to the controller insert method without a JSON model object.

I hope anybody can help me here.

  • 1
    Hey and welcome. The edit queue is full, so I cannot change your question. I would suggest use a better format for your code blocks. – KargWare Mar 03 '21 at 19:22
  • I went ahead and fixed some of it, but honestly, there's a lot of code here, and that's even without any of the JSON, which really should be in the question itself, not as a link to a URL to somewhere else that might disappear. – Heretic Monkey Mar 03 '21 at 21:31
  • Hi @Sivakumar N,What is your `K360DbCatgViewModel`? – Rena Mar 04 '21 at 02:53
  • Its model class file from another SQL table. It contains around 30 columns which are used to map JSON data – Sivakumar N Mar 04 '21 at 05:07
  • @Rena, Thanks a lot for your kind help. Code working fine. – Sivakumar N Mar 04 '21 at 06:25

1 Answers1

1

Here is a working demo you could follow:

Model:

public class ApiMapDbViewModel
{
    public string Value { get; set; }
    public string Key { get; set; }
}
public class K360mapMaster
{
    public string ClientCatalog { get; set; }
    public string K360catalog { get; set; }
}
public class K360DbCatgViewModel
{
    public string AA { get; set; }
    public string BB { get; set; }
    public string CC { get; set; }
    public string DD { get; set; }
}

View:

<table class="table" id="tb_properties" style="width:100%">
    <tr>
        @if (ViewBag.ApiProp != null)
        {
            @foreach (var itemApiProp in ViewBag.ApiProp)
            {
                <td>
                    <input type="text" value="@itemApiProp.Key" class="form-control" />

                    <select class="form-control">
                        <option value="">--Select-- </option>
                        @foreach (var itemK360Prop in ViewBag.K360Prop)
                        {
                            <option>@itemK360Prop.Key</option>
                        }
                    </select>
                </td>

            }
        }
    </tr>
    <tr>
        <td>
            <button type="submit" class="btn btn-primary" style="margin-
          right:50px">
                Catalog Mapping
            </button>
        </td>
    </tr>
</table>

JS(Add data: jsonstr,contentType:"application/json"):

@section scripts{
    <script>
        $(function () {
            $("button[type='submit']").click(function () {
                event.preventDefault();
                var properties = [];
                $("#tb_properties tr:first").find("td").each(function (index, item) {
                    var propertyname = $(item).find("input[type='text']").val();
                    var selctedvalue = $(item).find("select").val();
                    properties.push('"' + propertyname + '":"' + selctedvalue + '"');
                });
                var jsonstr = '{' + properties.join(",") + '}';
                //var jsobject = JSON.parse(jsonstr);
   
                $.ajax({
                    type: "Post",
                    url: "/KEMap/Insert",
                    //data: jsobject,
                    data: jsonstr,
                    contentType:"application/json",
                    success: function (response) {
                        toastr.info(response.status + "<br>" + "<br>" + response.message);
                        $("#tb_properties select").val("");
                        $("#partial_div").load(window.location.href + " #partial_div");
                    },
                    error: function (xhr, textStatus, errorThrown) {
                        console.log('in error');
                    }
                });

            });
        });
    </script>
}

Controller:

[HttpPost]
public IActionResult Insert([FromBody]JObject jsonModel)
{
    Type type = jsonModel.GetType();
    PropertyInfo[] props = type.GetProperties();
    List<K360mapMaster> K360mapListObj = new List<K360mapMaster>();
    foreach (JProperty prop in jsonModel.Children())
    {
        string key = prop.Name.ToString();
        string value = prop.Value.ToString();
        K360mapListObj.Add(new K360mapMaster() { ClientCatalog = key, K360catalog = value });
    }
       
    //do your stuff...
    return Json(new { Status = "Fail", Message = "Not done" });
}

Note 1:

Because the mapped property in ApiJsonViewModel capitalize the first letter,so the data you get here ClientCatalog = c.Name, is capital.From my provided code,The code here string key = prop.Name.ToString(); get the json(https://raw.githubusercontent.com/wedeploy-examples/supermarket-web-example/master/products.json) key name which is lower case.If you want to keep the first letter capital,you could change the following line:

string key = prop.Name.ToString().First().ToString().ToUpper() + prop.Name.ToString().Substring(1); 

Note 2:

If your project is asp.net core 3.x or asp.net 5,be sure your project has Newtonsoft support,otherwise,you cannot pass data to backend successfully.More details you could refer to:

.NET 5.0 MVC return Json is throwing a JSON Parser error

Result:

enter image description here

Rena
  • 30,832
  • 6
  • 37
  • 72
  • Thanks a lot. I Will implement your code and update you soon – Sivakumar N Mar 04 '21 at 05:11
  • Yes, I am working on asp.net core 5 only. – Sivakumar N Mar 04 '21 at 06:26
  • I need one more help regarding the table alignment issue. I have posted the issue with an updated answer section. Please have a look and kindly help me. – Sivakumar N Mar 04 '21 at 14:27
  • I have created a new thread https://stackoverflow.com/questions/66486022/dynamic-control-creation-issue-in-mvc-asp-net-core. Please help me out – Sivakumar N Mar 05 '21 at 02:56
  • Ok.Please wait a while. – Rena Mar 05 '21 at 03:06
  • I need to pass one hidden variable string from view to the controller along with the selected 2 control values. Will you please help me out by changing jQuery and controller insert method – Sivakumar N Mar 06 '21 at 00:33
  • I have created a new thread https://stackoverflow.com/questions/66501528/access-hidden-value-from-view-to-controller-in-asp-net-core-mvc. Please help me – Sivakumar N Mar 06 '21 at 01:32