ASP MVC knockout json nested foreach data binding - c#

Sorry if this particular question has been asked already, I have been through countless similar questions but none that seem to relate with my problem.
I am fairly new to MVC Web API's and working with JavaScript/knockout.
View model script - QuestionItems.js
var SectionModel = function (data) {
var self = this;
self.SectionName = ko.observable(data.SectionName);
self.SectionNumber = ko.observable(data.SectionNumber);
self.Questions = ko.observableArray();
};
var questionnaireViewModel = function () {
self.sections = ko.observableArray();
self.error = ko.observable();
var itemsUri = '/api/QuestionnaireItems/';
var sectionsUri = '/api/QuestionnaireSections/';
function ajaxHelper(uri, method, data) {
self.error('');
return $.ajax({
type: method,
url: uri,
dataType: 'json',
contentType: 'application/json',
data: data ? JSON.stringify(data) : null
}).fail(function (jqXHR, textStatus, errorThrown) {
self.error(errorThrown);
});
}
function getAllQuestions() {
ajaxHelper(itemsUri, 'GET').done(function (data) {
for (var s = 0; s < self.sections.length; s++) {
// find all the questions for this section
var sectionQuestions = data.filter(function (item) {
return item.SectionName == self.sections[s].SectionName;
});
// add the questions to each section
self.sections.Questions(sectionQuestions);
}
});
}
function getAllSections() {
ajaxHelper(sectionsUri, 'GET').done(function (data) {
// map each data item to a SectionModel and store that in your main viewModel
var sectionsTemp = data.map(function (item) {
return new SectionModel(item);
});
self.sections(sectionsTemp);
});
}
getAllSections();
getAllQuestions();
};
ko.applyBindings(questionnaireViewModel);
And my view - Index.cshtml
#section scripts {
#Scripts.Render("~/bundles/QuestionItems")
}
<div class="col-lg-12">
<h1 class="page-header">SQA</h1>
<ul class="list-unstyled" data-bind="foreach: sections">
<li>
<div class="panel panel-default">
<div class="panel-heading">
<div><strong data-bind="text: SectionNumber"></strong>. <strong data-bind="text: SectionName"></strong></div>
</div>
<div class="panel-body">
<ul data-bind="foreach: Questions">
<li>
<span data-bind="text: QuestionNumber"></span>. <span data-bind="text: QuestionName"></span>
</li>
</ul>
</div>
</div>
</li>
</ul>
</div>
In the database I have a QuestionnaireItems table which stores all question details and a foreign key to the sections table to retrieve each questions related section :
QuestionnaireItems
And a QuestionnaireSections table which holds each sections name and order number :
QuestionnaireSections
I have managed to get the sections displaying, however the questions are not. If I pull through just the questions without matching them to their correct sections they display. I'm assuming this is a problem with the way the condition is set up but I am at a complete loss as to how I can fix this.
I have also tested the controllers in Postman and all the correct data is pulling through.
QuestionItemList.cs (DTO):
public class QuestionItemList
{
public int Id { get; set; }
public int SectionNumber { get; set; }
public string SectionName { get; set; }
public int QuestionNumber { get; set; }
public string QuestionName { get; set; }
}
SectionItemList.cs (DTO)
public class SectionItemList
{
public int Id { get; set; }
public int SectionNumber { get; set; }
public string SectionName { get; set; }
}
QuestionnaireItemsController:
public class QuestionnaireItemsController : ApiController
{
private SQAContext db = new SQAContext();
// GET: api/QuestionnaireItems
[HttpGet]
public IQueryable<QuestionItemList> GetItems()
{
var items = from a in db.QuestionnaireItems
select new QuestionItemList()
{
Id = a.PID,
SectionNumber = a.QuestionnaireSection.Number,
SectionName = a.QuestionnaireSection.Name,
QuestionNumber = a.Number,
QuestionName = a.Name
};
return items;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool QuestionnaireItemExists(int id)
{
return db.QuestionnaireItems.Count(e => e.PID == id) > 0;
}
}
QuestionnaireSectionsController:
public class QuestionnaireSectionsController : ApiController
{
private SQAContext db = new SQAContext();
// GET: api/QuestionnaireSections
[HttpGet]
public IQueryable<SectionItemList> GetSectionItems()
{
var items = from a in db.QuestionnaireSections
select new SectionItemList()
{
Id = a.PID,
SectionNumber = a.Number,
SectionName = a.Name
};
return items;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool QuestionnaireSectionExists(int id)
{
return db.QuestionnaireSections.Count(e => e.PID == id) > 0;
}
}

Related

How can I re-order divs using 2 buttons and save the order?

I have mulitple divs that are dipslayed using a foreach loop and i want to be able re-order using 2 buttons and i also want be able to save this order so when i come back on after refreshing the page the new order is still present.
**What I have done so far **
I have managed to use JavaScript to move the html elements up and down using 2 buttons. I have also added public int OrderNum to the public class Lesson and I have made the divs order by increasing OrderNum. However i'm struggling to be able to change the orderNumm when the button is of each div when the buttons are pressed.
C#
public class Lesson : IModel
{
public override String partitionKey { get => CourseId; }
[Required]
public string CourseId { get; set; }
[Required]
[StringLength(256, ErrorMessage = "Maximum {1} characters")]
public string Title { get; set; }
[Required]
public string Content { get; set; }
public string ImageID { get; set; }
public string ImageURL { get => (ImageID != null) ? Storage.Image.Path(ImageID) : null; }
public int OrderNum { get; set; }
}
HTML
#foreach (var Lesson in Model.Lessons.OrderBy(x => x.OrderNum))
{
<li class="list-group-item">
#Lesson.OrderNum
#if (AppUser.CurrentUser.Areas.Admin)
{
<a class='up' href='#'><i class="fa-solid fa-arrow-up fa-lg"></i></a> <a class='down' href='#'><i class="fa-solid fa-arrow-down fa-lg"></i></a>
<div class="Edit-Buttons-L">
<div>
<a href="#Url.Action("EditLesson", "Lesson", new { CourseCategory = Model.Course.Category, CourseID = Model.Course.id, Lesson.id })">
<i class="fa-regular fa-pen-to-square fa-lg"></i>
</a>
</div>
<div>
<form action="#Url.Action("DeleteLesson","Lesson", new{CourseCategory = Model.Course.Category, CourseID = Model.Course.id, Lesson.id})" method="post">
<button type="submit" class="fa-regular fa-trash-can fa-lg" value="Delete"></button>
</form>
</div>
</div>
}
</li>
}
JavaScript
window.onload = function () {
var upLink = document.querySelectorAll(".up");
for (var i = 0; i < upLink.length; i++) {
upLink[i].addEventListener('click', function () {
var wrapper = this.parentElement;
if (wrapper.previousElementSibling)
wrapper.parentNode.insertBefore(wrapper, wrapper.previousElementSibling);
});
}
var downLink = document.querySelectorAll(".down");
for (var i = 0; i < downLink.length; i++) {
downLink[i].addEventListener('click', function () {
var wrapper = this.parentElement;
if (wrapper.nextElementSibling)
wrapper.parentNode.insertBefore(wrapper.nextElementSibling, wrapper);
});
}
I have not tested the upcoming codes, just to create an insight:
First: Add an attribute to each "list-group-item" element to you can relate them to the server object in future.
<li class="list-group-item" data-elementid="#Lesson.id">
Then at click event handlers post new orders to the server to be set to the objects:
upLink[i].addEventListener('click', function () {
var wrapper = this.parentElement;
if (wrapper.previousElementSibling)
wrapper.parentNode.insertBefore(wrapper, wrapper.previousElementSibling);
var elements= document.querySelectorAll(".list-group-item");
var stringToBeSend='';
for (var j = 0; j < elements.length; j++) {
stringToBeSend+=elements[j].getAttribute("data-elementid")+":"+j+",";
}
fetch('[Address to a new controller to save new positions. e.g. /api/lessons/UpdatePositions]', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: stringToBeSend})
.catch(error => console.error('Unable to post positions.', error));
});
Now you need a controller to get the comma separated string and update new lesson positions. For example:
[HttpPost("UpdatePositions")]
public IActionResult UpdatePositions(string commaSepPositions)
{
var valueLists = commaSepPositions.Split(',');
foreach(var value in valueLists)
{
if (!string.IsNullOrWhiteSpace(value))
{
var positions = value.Split(':');
if (positions.Length > 1)
{
var lessonIDStr = positions[0];
var newPositionStr = positions[1];
}
//Now update entity in db
}
}
return Ok();
}

How would i get the data from each event from a jsonResult with full calendar

I'm attempting to get event data (Title, date,etc) for an event when clicked but I can't figure out a way to do it since I add the data through the JSON result and full calendar javascript. If I cant, is there a better way to allow the backend razorpage to send data to the full calendar javascript?
backend
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using DynaHealth.Models;
using Microsoft.AspNetCore.Http;
namespace TeleHealthB.Pages
{
public class CalendarModel : PageModel
{
// public IndexModel(TeleHealthB.Models.HealthProjectContext context)
//{
// healthProject = context;
//}
[BindProperty]
public string Title { get; set; }
[BindProperty]
public string Doc { get; set; }
[BindProperty]
public string Pat { get; set; }
[BindProperty]
public string dec { get; set; }
[BindProperty]
public DateTime date { get; set; }
[BindProperty]
public JsonResult result { get; set; }
public string today = DateTime.Today.ToString();
public void OnGet()
{
// result = (JsonResult)OnGetEvents();
}
public class eventShow
{
public int id { get; set; }
public string title { get; set; }
public string description { get; set; }
public string start { get; set; }
public string end { get; set; }
//public string description { get; set; }
// public string patient { get; set; }
// public string doctor { get; set; }
}
private DynaHealth2Context db;
public CalendarModel(DynaHealth2Context _db)
{
db = _db;
}
public IActionResult OnGetEvents()
{
List<eventShow> events = new List<eventShow>();
eventShow show = new eventShow();
try
{
string x = HttpContext.Session.GetString("Username");
using (var context = new DynaHealth2Context())
{
var query = from st in context.Appointments
where st.PatientEmail == x.Trim() || st.ProviderEmail == x.Trim()
select st;
// foreach (var item in query.ToList())
// {
// show.id = item.Id;
// show.title = item.Title;
// show.description = item.Description;
// show.start = item.Start.ToString("MM/dd/yyyy");
//show.end = item.End.ToString("MM/dd/yyyy");
// events.Add(show);
// }
return new JsonResult(query.ToList());
}
}
catch { return null; }
}
public IActionResult OnGetADDEvent(string sub)
{
// using (var context = new HealthProjectContext())
{
try
{
//context.Schedules.Add(schedule);
return null;
}
catch { return null; };
}
}
// public onPost()
// {
// RedirectToPage("./Meeting");
// }
public IActionResult OnPostRemoveEvent(string sub)
{
// using (var context = new HealthProjectContext())
{
try
{
// context.Schedules.Add(schedule);
return null;
}
catch { return null; };
}
}
}
}
frontend
#model TeleHealthB.Pages.CalendarModel
#{
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title>Calendar</title>
<link href='~/lib/TestCalendar/main.css' rel='stylesheet' />
<script src='~/lib/TestCalendar/main.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
initialDate: Date.now(),
navLinks: true, // can click day/week names to navigate views
selectable: true,
selectMirror: true,
select: function (arg) {
var title = prompt('Reasining For meeting:');
if (title) {
var tie = prompt('Time');
}
if (title) {
calendar.addEvent({
title: title,
start: arg.start,
Starttime: tie,
end: arg.end,
EndTime: arg.EndTime
})
}
calendar.unselect()
},
eventClick: function (event, jsEvent, view) {
window.open("/Meeting", "_blank");
return false
},
editable: false,
dayMaxEvents: true, // allow "more" link when too many events
events: "/calendar?handler=events"
});
calendar.render();
});
</script>
<style>
#calendar {
max-width: 1100px;
margin: 0 auto;
}
</style>
</head>
<body>
<h1>Schedule View</h1>
<div id='calendar'></div>
<div id="fullCalModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span aria-hidden="false">x</span>
<span class="sr-only">Close</span>
</button>
<h4 id="modalTItle" class="modal-title"> </h4>
</div>
<div id="modalBody" class="modal-body"></div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" name="del" class="btn btn-default" id="eventURL">Delete</button>
<a class="btn btn-primary" id="eventURL" target="_blank">Schedule</a>
</div>
</div>
</div>
</div>
</body>
</html>
}
If you want to get the event in the backend,you can do following change:
You can use code var events = calendar.getEvents(); to get all the events,and then push the property you want in the array,the pass the arry to the backend.
Frontend
//Add a button to get event:
<button id="GetEvent">Get Event</button>
//....
document.addEventListener('DOMContentLoaded', function () {
var calendarEl = document.getElementById('calendar');
var calendar = new FullCalendar.Calendar(calendarEl, {
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay'
},
initialDate: Date.now(),
navLinks: true, // can click day/week names to navigate views
selectable: true,
selectMirror: true,
select: function (arg) {
var title = prompt('Reasining For meeting:');
if (title) {
var tie = prompt('Time');
}
if (title) {
calendar.addEvent({
title: title,
start: arg.start,
Starttime: tie,
end: arg.end,
EndTime: arg.EndTime
})
}
calendar.unselect()
},
eventClick: function (event, jsEvent, view) {
window.open("/Meeting", "_blank");
return false
},
editable: false,
dayMaxEvents: true, // allow "more" link when too many events
events: "/calendar?handler=events"
});
calendar.render();
//add following
$("#GetEvent").click(function () {
var events = calendar.getEvents();
var e = [];
$.each(events, function (index, value) {
console.log(value.start);
console.log(index);
var start_time = value.start;
var end_time = value.end;
var id = parseInt(value.id);
var slot = {
start: start_time,
end: end_time,
id: id,
};
e.push(slot);
});
$.ajax({
url: '/test?handler=getevents',
contentType:"application/json",
data: JSON.stringify(e),
dataType: "json",
type: "POST",
});
});
});
Backend:
//add this line
[IgnoreAntiforgeryToken]
public class TestModel : PageModel
{
[BindProperty]
public string Title { get; set; }
[BindProperty]
public string Doc { get; set; }
[BindProperty]
public string Pat { get; set; }
[BindProperty]
public string dec { get; set; }
[BindProperty]
public DateTime date { get; set; }
//delete this line
//[BindProperty]
public JsonResult result { get; set; }
public string today = DateTime.Today.ToString();
public void OnGet()
{
JsonResult result = (JsonResult)OnGetEvents();
}
public class eventShow
{
public int id { get; set; }
public string title { get; set; }
public string description { get; set; }
public string start { get; set; }
public string end { get; set; }
}
public IActionResult OnGetEvents()
{
}
public void OnPostGetEvents([FromBody]List<eventShow> model)
{
}
Test result:

Save jQuery JSON object into SQL table without creating View model class in MVC ASP.NET Core

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.
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:

Get infos of submit button after a foreach

I try to put some info into a new modal :
when I click on a button I want to open a new modal with good info of clicked pokemon.
I made controller :
public IActionResult Index()
{
#region ListeDesPokemons
var pokemonList = new List<PokemonModel>();
var Id = 1;
var Img = 1;
pokemonList.Add(new PokemonModel() { Id = Id++, Name = "Bulbizarre", UsName = "Bulbasaur(us)", JpName = "フシギダネ(jp)", Type1 = "Plante", Type2 = "Poison", Rate = 45, Image = "https://www.pokemontrash.com/pokedex/images/sugimori/00" + Img++ + ".png" });
pokemonList.Add(new PokemonModel() { Id = Id++, Name = "Herbizarre", UsName = "Ivysaur(us)", JpName = "フシギソウ(jp)", Type1 = "Plante", Type2 = "Poison", Rate = 45, Image = "https://www.pokemontrash.com/pokedex/images/sugimori/00" + Img++ + ".png" });
var model = new PokemonViewModel();
model.Pokemons = pokemonList;
return View(model);
I made a Viewmodel :
public List<PokemonModel> Pokemons { get; set; }
public List<PokeBallModel> PokeBalls { get; set; }
public List<PokemonStatutModel> PokemonStatuts { get; set; }
}
I made a Model :
public int Id { get; set; }
public string Name { get; set; }
public string UsName { get; set; }
public string JpName { get; set; }
public string Type1 { get; set; }
public string Type2 { get; set; }
public int Rate { get; set; }
public string Image { get; set; }
I made a view :
#foreach (var pokemon in Model.Pokemons){ #pokemon.Id,#pokemon.Name #pokemon.Image}
here a picture of the first modal on the back of the screen with all pokemon list (foreach)
and the second modal on the front of the screen with no info.
please help.
I think you don't need to use form and should use ajax, when user click the picture of pokemon, you call an ajax with the Id of this pokemon, and in the controller you search all infos of pokemon with Id, and success in ajax just add infomations to the modal dialog. Something like:
<img class="align-self-center" id="tailleImg" src="#pokemon.Image" alt="#pokemon.Name" onclick="getInfo(#pokemon.Id)" />
function getInfo(val)
{
$.ajax({
url: '/yourController/yourActionToGetInfo',
type: "POST",
dataType: "json",
data: { "pokeId": val},
success: function (data) {
$("#pokeId").val(data.Id);
}
})
}
ok
In my view, in my foreach I add :
#foreach (var pokemon in Model.Pokemons)
{
<div class="col">
<button data-pokemon-id="#pokemon.Id" type="submit" class="btn" onclick="getInfo();">
<div class="card text-center rounded-lg">
<div id="tailleCard" class="card-body">
<h5 id="cardTitle" class="card-title">n°#pokemon.Id <br /> #pokemon.Name</h5>
<img id="tailleImg" src="#pokemon.Image" alt="#pokemon.Name" />
</div>
</div>
</button>
</div>
}
# the end of the view I add : But the Request does not exist in the current context nedd help please.
<script>
function getInfo() {
$.post('#(Url.Action("PokemonDetails", "Pokedex", null, Request.Url.Scheme))?pokemonId=' +
$(this).data("pokemon-id"))
.done(function (response) {
$("#divContent").empty();
$("#divContent").html(response);
$("#divContent").html(response);
$('#pokemonDetailsModal').modal('show');
});
</script>
In the controller I add a :
public IActionResult PokemonDetails(int pokemonId)
{
var model = new PokemonDetails();
return PartialView("_PokemonDetails", model);
}
I also made a Partial view _ and a PokemonDetail Model
public class PokemonDetails
{
public string Name { get; set; }
}
What I try to do it's to take the data of the selected pokemon (with the button in the foreach) and put the data of the selected pokemon in New Modal.
OK i almost there ! cool
in the view
...
#foreach (var pokemon in Model.Pokemons)
{
<button type="submit" class="btn" onclick="getInfo(#pokemon.Id)">
<div class="card text-center rounded-lg">
<div id="tailleCard" class="card-body">
<h5 id="cardTitle" class="card-title">n°#pokemon.Id <br /> #pokemon.Name</h5>
<img id="tailleImg" src="#pokemon.Image" alt="#pokemon.Name" />
</div>
</div>
</button>
}
...
at the end of the view page :
<script>
function getInfo(val) {
event.preventDefault;
//debug log
console.log('Star getInfo()');
$.ajax({
url: '/Pokedex/PokemonDetails/',
type: 'POST',
dataType: "html",
data: { "PokemonId": val },
//data: json,
//contentType: 'application/json; charset=utf-8',
success: function (response) {
//debug log
console.log(val);
$("#pokemonDetails").html(response);
$('#pokemonDetails').modal('show');
}
})
}
</script>
in the controller :
[HttpPost]
public IActionResult PokemonDetails(int PokemonId)
{
int SelectedPokemonId = PokemonId;
TempData["SelectedPokemonId"] = SelectedPokemonId;
ToDoo : Get Info of the pokemon from the Id
return PartialView("_PokemonDetails");
}
How I can get the info of the selected pokemon from the selected Id???
https://i.stack.imgur.com/atajO.png
[HttpPost]
public IActionResult PokemonDetails(int PokemonId)
{
int SelectedPokemonId = PokemonId;
TempData["SelectedPokemonId"] = SelectedPokemonId;
ToDoo : Get Info of the pokemon from the Id
return PartialView("_PokemonDetails");
}
Do you have database ? if you have just call:
return (db.PokemonModel.FirstOrDefault(n=>n.Id == PokemonId));
and if you don't have use the list you use in action Index:
return pokemonList.FirstOrDefault(n=>n.Id == PokemonId));
and in sucess ajax:
success: function (response) {
$("#cardTitle").html("n°" + response.Id +"<br />" + response.Name");
$("#tailleImg").attr('src', response.Image);
$("#tailleImg").attr('name', response.Name);
$('#pokemonDetails').modal('show');
}

Rating Record Is Not getting save in database

Controller=>>
view is sending data to SendRating and this method is responsible for storing data in database,,but data is not getting saved.
only authenticated user can rate ,but every time we faced rating failed..i can't understand what exactly the problem is.
public ActionResult SendRating(string r, string s, string id, string url)
{
try {
var context = new ApplicationDbContext();
string currentUserId = User.Identity.GetUserId();
int autoid = 0;
Int16 thisVote = 0;
Int16 O_ServID = 0;
Int16.TryParse(s, out O_ServID);
Int16.TryParse(r, out thisVote);
int.TryParse(id, out autoid);
if (!User.Identity.IsAuthenticated)
{
return Json("Not authenticated!");
}
switch (s)
{
case "5":
//var isIt = db.VoteModel.Where(v => v.O_ServID == O_ServID && v.UserId.Equals(User.Identity.Name, StringComparison.CurrentCultureIgnoreCase) && v.WorkerID == autoid).FirstOrDefault();
var service = context.OrderServices.Where(o => o.O_ServID == O_ServID).Single();
var worker = context.Workers.Where(w => w.WorkerID == autoid).Single();
var store = new UserStore<ApplicationUser>(new ApplicationDbContext());
var userManager = new UserManager<ApplicationUser>(store);
var user = userManager.FindByName(User.Identity.Name);
VoteModel vm = new VoteModel()
{
Active = true,
//id
UserId = User.Identity.GetUserId(),
Votes = thisVote,
WorkerID = autoid,
O_ServID = O_ServID,
OrderServices = service,Workers = worker,User = user
};
var save = context.VoteModel.Add(vm);
if(db.SaveChanges() > 0)
{
HttpCookie cookie = new HttpCookie(url, "true");
Response.Cookies.Add(cookie);
return Json("<br />You rated " + r + " star(s), thanks !", JsonRequestBehavior.AllowGet);
}
// keep the school voting flag to stop voting by this member
//HttpCookie cookie = new HttpCookie(url, "true");
//Response.Cookies.Add(cookie);
//}
break;
default:
break;
}
return Json("Rating Failed!", JsonRequestBehavior.AllowGet);
}
catch (Exception ex)
{
HttpCookie cookie = new HttpCookie(url, "true");
Response.Cookies.Add(cookie);
return Json(ex.Message, JsonRequestBehavior.AllowGet);
throw;
}
}
public ActionResult VoteNow(int id, int serv)
{
ViewData["id"] = id;
ViewData["serv"] = serv;
return View();
}
public ActionResult VoteShow()
{
return View();
}
Model==>>
this is table schema where record has to be stored..
namespace WebApplication5.Models
{
public class VoteModel
{
[Key]
public int AutoId { get; set; }
public int O_ServID { get; set; }
public OrderService OrderServices { get; set; }
public int WorkerID { get; set; }
public Worker Workers { get; set; }
public Int16 Votes { get; set; }
public bool Active { get; set; }
[Required]
public string UserId { get; set; }
public ApplicationUser User { get; set; }
}
}
view==>>
my view code is as follows...
sending data with json to controller with different parameters pass through ViewData[] ..
#{
ViewBag.Title = "VoteNow";
Layout = "~/Views/Shared/_LayoutUser.cshtml";
}
<div id="page-wrapper">
<div id="page-inner">
<h2>VoteNow</h2>
#model string
#{
var url = Request.Url.AbsolutePath;
}
#if (Request.Cookies[url] == null)
{
<div id="ratingDiv" class="smallText">
Poor
<img src="/img/whitestar.gif" alt="" class="ratingStar" data-value="1" /><img src="/img/whitestar.gif" alt="" class="ratingStar" data-value="2" /><img src="/img/whitestar.gif" alt="" class="ratingStar" data-value="3" /><img src="/img/whitestar.gif" alt="" class="ratingStar" data-value="4" /><img src="/img/whitestar.gif" alt="" class="ratingStar" data-value="5" /> Excellent
<label id="lblResult"></label>
</div>
<style type="text/css">
.ratingStar {
cursor: pointer;
height: 20px;
width: 20px;
}
</style>
}
else
{
<text><span style="color:green;"> Thanks for your vote !</span></text>
}
#section scripts{
<script type="text/javascript">
var clickedFlag = false;
$(".ratingStar").mouseover(function () {
$(this).attr("src", "/img/yellowstar.gif").prevAll("img.ratingStar").attr("src", "/img/yellowstar.gif");
});
$(".ratingStar, #radingDiv").mouseout(function () {
$(this).attr("src", "/img/whitestar.gif");
});
$("#ratingDiv").mouseout(function () {
if (!clickedFlag) {
$(".ratingStar").attr("src", "/img/whitestar.gif");
}
});
$(".ratingStar").click(function () {
clickedFlag = true;
$(".ratingStar").unbind("mouseout mouseover click").css("cursor", "default");
var url = "/CDashboard/SendRating?r=" + $(this).attr("data-value") + "&s=#((int)ViewData["serv"])&id=#((int)ViewData["id"])&url=#url";
$.post(url, null, function (data) {
$("#lblResult").html(data);
});
});
$("#lblResult").ajaxStart(function () {
$("#lblResult").html("Processing ....");
});
$("#lblResult").ajaxError(function () {
$("#lblResult").html("<br />Error occured.");
});
</script>
}
</div>
</div>

Categories