Refer to the comment inside the ajax success function:
function CreateProjectTree(sc)
{
$.ajax({
type: "POST",
url: "../api/projects/SearchProjects",
data: sc,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data)
{
if ($(data).length === 1)
{
window.location.replace("../ViewProjectDetails.aspx?ProjectId=" + //here's where I need to get the id;
}
else
{
buildTree(data);
}
},
});
}
This is what the controller looks like for the post:
public class ProjectsController : ApiController
{
public List<Item> SearchProjects(GBLProjectSearchCriteria searchCriteria)
{
var ProjectSearchResult = new ProjectSearchResultController();
searchCriteria.SearchType = "P";
searchCriteria.QueryString = "?ProjectId=";
var GBLProjectSearchResultListData = ProjectSearchResult.GetProjectSearchResultList(searchCriteria);
var projectList = (from GBLProjectSearchResult item in GBLProjectSearchResultListData
select new Item
{
Id = item.Id,
Title = item.Title,
Url = item.NavigateUrl + item.QueryString
}).ToList();
foreach (var project in projectList)
{
//seasons
project.Items = new List<Item>();
var SeasonSearchResult = new ProjectSearchResultController();
searchCriteria.Id = project.Id;
searchCriteria.SearchType = "S";
searchCriteria.QueryString = "?ProjectId=" + project.Id + "&SeasonId=";
var GBLSeasonSearchResultListData = SeasonSearchResult.GetProjectSearchResultList(searchCriteria);
foreach (var season in from GBLProjectSearchResult item in GBLSeasonSearchResultListData
select new Item
{
Id = item.Id,
Title = item.Title,
Url = item.NavigateUrl + item.QueryString
})
{
project.Items.Add(season);
project.HasChildren = (project.Items.Count > 0);
}
foreach (var season in project.Items)
{
//episodes
season.Items = new List<Item>();
var episodeSearchResult = new ProjectSearchResultController();
searchCriteria.Id = season.Id;
searchCriteria.SearchType = "E";
searchCriteria.QueryString = "?ProjectId=" + project.Id + "&SeasonId=" + season.Id + "&EpisodeId=";
var GBLEpisodeSearchResultListData = episodeSearchResult.GetProjectSearchResultList(searchCriteria);
foreach (GBLProjectSearchResult item in GBLEpisodeSearchResultListData)
{
var episode = new Item
{
Id = item.Id,
Title = item.Title,
Url = item.NavigateUrl + item.QueryString
};
season.Items.Add(episode);
season.HasChildren = (season.Items.Count > 0);
}
}
}
return projectList;
}
public class Item
{
readonly string take2Root = ConfigurationManager.AppSettings["Take2Root"];
private string url;
public int Id
{
get;
set;
}
public string Title
{
get;
set;
}
public bool HasChildren
{
get;
set;
}
public List<Item> Items
{
get;
set;
}
public string Url
{
get
{
return url;
}
set
{
url = take2Root + value.Replace("..", "");
}
}
}
}
I need to get the ID of the parent node returned by this controller.
I would know how to work with a GET request, however, I have to do a POST here and I'm unsure on how to extract the ID inside the ajax success function.
Can someone give me a hand?
Thanks!
inside your if ($(data).length === 1) statement you can add debugger; (or set a break-point) then examine the data object using chrome's developer tools. The id you're after will be something like data.objects[0].id
Related
I am working on e-commerce site. I want to filter product based on multiple check boxes. I use ajax. It sends check boxes' IDs to the controller. But selected counts zero like in the picture. What is wrong with this code?
Ajax:
<script type="text/javascript">
$(function () {
$('.filterprod').click(function () {
var ProdID = "";
$('.checks').each(function () {
if ($(this).is(':checked')) {
ProdID += $(this).val() + ",";
}
});
var data = {};
data.Id = ProdID.slice(0, ProdID.length - 1);
$.ajax({
url: '/Shop/GetProd',
method: 'POST',
dataType: "json",
contentType: 'application/json',
data: JSON.stringify(data),
success: function (response) {
$("#Prodlist").remove();
},
error: function (err, response) {
console.log(err, response);
alert(err, response.responseText);
}
})
});
});
</script>
Controller:
[HttpPost]
public JsonResult GetProd(string Id)
{
var ids = new List<int>();
IQueryable<Product> prods = null;
if (!string.IsNullOrEmpty(Id))
{
for (int i = 0; i < Id.Split(',').Length; i++)
{
ids.Add(Convert.ToInt32(Id.Split(',')[i]));
}
prods =_context.Products.Where(t => ids.Contains(t.id));
}
else
{
prods = _context.Products.Take(5);
}
var selected = (from v in prods
select new
{
v.ProdName,
v.Price,
v.Description
}).ToList();
return Json(selected, JsonRequestBehavior.AllowGet);
}
Try to do it in a console like this: https://dotnetfiddle.net/AMwxiP
using System;
using System.Collections.Generic;
using System.Linq;
public class Product
{
public int Id { get; set; }
public string ProdName { get; set; }
public decimal? Price { get; set; }
public string Description { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
IQueryable<Product> products = (new List<Product> {
new Product
{
Id = 1,
},
new Product
{
Id = 2,
}
}).AsQueryable<Product>();
var Id = "1,2";
var ids = new List<int>();
IQueryable<Product> prods = null;
if (!string.IsNullOrEmpty(Id))
{
for (int i = 0; i < Id.Split(',').Length; i++)
{
ids.Add(Convert.ToInt32(Id.Split(',')[i]));
}
prods = products.Where(t => ids.Contains(t.Id));
}
else
{
prods = products.Take(5);
}
var selected = (from v in prods
select new
{
v.ProdName,
v.Price,
v.Description
}).ToList();
Console.WriteLine(selected.Count);
}
}
I am working on a request form for work. The request deals with series of products. There are many series, so I am trying to filter them down by the product line that they are produced on. I am attempting this using cascading dropdown lists from Ajax. I know the script is working to a degree, because the default selected option changes to "Make Selection". However, the rest of the dropdown does not populate.
Here are the two dropdowns.
#Html.DropDownListFor(model => model.SelectedProductLine, new SelectList(Model.ProductLines, "Value", "Text"), "Select a Product Line", new { #class = "form-control", #style = "width: 400px;", #id = "ProductLineID"})
#Html.DropDownListFor(model => model.SelectedSeries, new SelectList(string.Empty, "Value", "Text"), "Select a Series", new { #class = "form-control", #id = "SeriesID"})
The Ajax Script.
$(document).ready(function () {
//Dropdownlist Selectedchange event
$('#ProductLineID').change(function () {
$.ajax({
url: '/SMRMaster/RequestForm/GetSeries',
type: 'GET',
datatype: 'JSON',
data: { id: $('#ProductLineID').val() },
success: function (result) {
$('#SeriesID').html('');
$('#SeriesID').append($('<option>Make Selection</option>'));
$.each(result, function (index, item) {
$('#SeriesID').append($('<option></option>').val(item.Value).html(item.Text));
});
}
});
});
});
The Controller.
public JsonResult GetSeries(string id)
{
int Id = Convert.ToInt32(id);
db.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNOCMMITTED;");
var productLineName = "";
switch (Id)
{
case 0:
productLineName = "Electric";
break;
case 1:
productLineName = "Europe Gas";
break;
case 2:
productLineName = "Gas";
break;
case 3:
productLineName = "Miscellaneous";
break;
case 4:
productLineName = "Water";
break;
default:
productLineName = "Electric";
break;
}
IEnumerable<SelectListItem> series = (from s in db.Series
where s.ProductLineName == productLineName
select new SelectListItem { Value = s.ProductLineName, Text = s.ProductLineName }).ToList();
return Json(series, JsonRequestBehavior.AllowGet);
}
public List<ProductLine> GetProductLines()
{
db.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");
var productLineList = (from p in db.ProductLines
select p).ToList();
return productLineList;
}
public ActionResult RequestForm()
{
var count = 0;
var productLineList = new List<SelectListItem>();
foreach (var item in GetProductLines())
{
productLineList.Add(new SelectListItem { Text = item.ProductlineName, Value = count.ToString() });
}
db.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");
var requestViewModel = new RequestViewModel { SMRMaster = new SMRMaster(), Engineers = GetEngineers(), ProductLines = productLineList };
return View(requestViewModel);
}
And the view model.
public class RequestViewModel
{
public List<SelectListItem> ProductLines { get; set; }
public string SelectedProductLine { get; set; }
public SMRMaster SMRMaster { get; set; }
public List<string> Engineers { get; set; }
[Required(ErrorMessage = "Engineer is required.")]
public string SelectedEngineer { get; set; }
public List<Series> Series { get; set; }
public string SelectedSeries { get; set; }
}
I do not know where the error is coming from. Any help is appreciated.
Try this
$.each(result, function (i, item) {
var optionData = '<option value="' + item.Value + '">' + obj.Text + '</option>';
$(optionData).appendTo('#SeriesID')
});
Or debug and see what's your response from server.
A colleague helped me solve this problem. Firstly, the Ajax script was using the wrong URL. Secondly, my controller functions were unnecessarily complicated.
Here is the updated AJAX script:
$(document).ready(function () {
//Dropdownlist Selectedchange event
$('#ProductLine').change(function () {
$.ajax({
url: '/SMRMaster/GetSeries',
type: 'GET',
datatype: 'JSON',
data: { productLine: $('#ProductLine').val() },
success: function (result) {
$('#SeriesID').html('');
$('#SeriesID').append($('<option>Make Selection</option>'));
$.each(result, function (i, item) {
var optionData = '<option value="' + item.Value + '">' + item.Text + '</option>';
$(optionData).appendTo('#SeriesID')
});
}
});
});
});
And here is the updated Controller:
public JsonResult GetSeries(string productLine)
{
db.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");
List<SelectListItem> series = (from s in db.Series
where s.ProductLineName == productLine
select new SelectListItem { Value = s.SeriesName, Text = s.SeriesName }).Distinct().ToList();
return Json(series, JsonRequestBehavior.AllowGet);
}
public List<ProductLine> GetProductLines()
{
db.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");
var productLineList = (from p in db.ProductLines
select p).ToList();
return productLineList;
}
public ActionResult RequestForm()
{
var productLineList = new List<SelectListItem>();
foreach (var item in GetProductLines())
{
productLineList.Add(new SelectListItem { Text = item.ProductlineName, Value = item.ProductlineName });
}
db.Database.ExecuteSqlCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");
var requestViewModel = new RequestViewModel { SMRMaster = new SMRMaster(), Engineers = GetEngineers(), ProductLines = productLineList };
return View(requestViewModel);
}
my entity
public class Agent
{
[Key]
[JsonProperty(PropertyName = "agentId")]
public int AgentId { get; set; }
[JsonProperty(PropertyName = "codeName")]
public string CodeName { get; set; }
[JsonProperty(PropertyName = "firstName")]
public string FirstName { get; set; }
[JsonProperty(PropertyName = "lastName")]
public string LastName { get; set; }
[JsonProperty(PropertyName = "imagePath")]
public string ImagePath { get; set; }
[JsonProperty(PropertyName = "description")]
public string Description { get; set; }
}
my Viewmodel
public class AgentVm
{
public int AgentId { get; set; }
public string CodeName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string ImagePath { get; set; }
public string Description { get; set; }
}
my Get web api controller
public IQueryable<AgentVm> GetAgents()
{
var agents = from b in db.Agents
select new AgentVm()
{
AgentId = b.AgentId,
FirstName = b.FirstName,
LastName = b.LastName,
CodeName = b.CodeName,
ImagePath = b.ImagePath
};
return agents;
}
my post web api controller
public async Task<HttpResponseMessage> PostAgent(Agent agent)
{
if (agent != null)
{
// Extract the image from the image string
string regEx = "data:(.+);base64,(.+)";
Match match = Regex.Match(agent.ImagePath, regEx);
if (match.Success)
{
// Get the content-type of the file and the content
string imageType = match.Groups[1].Value;
string base64image = match.Groups[2].Value;
if (imageType != null && base64image != null)
{
// Verify the content-type is an image
string imageRegEx = "image/(.+)";
match = Regex.Match(imageType, imageRegEx);
if (match.Success)
{
// Get the file extension from the content-type
string fileExtension = match.Groups[1].Value;
// Get the byte-array of the file from the base64 string
byte[] image = Convert.FromBase64String(base64image);
string path = HttpContext.Current.Server.MapPath("~/images");
string fileName = agent.FirstName + agent.LastName;
// Generate a unique name for the file (add an index to it if it already exists)
string targetFile = fileName + "." + fileExtension;
int index = 0;
while (File.Exists(Path.Combine(path, targetFile)))
{
index++;
targetFile = fileName + index + "." + fileExtension;
}
// Write the image to the target file, and update the agent with the new image path
File.WriteAllBytes(Path.Combine(path, targetFile), image);
agent.ImagePath = "images/" + targetFile;
db.Agents.Add(agent);
await db.SaveChangesAsync();
// Create the Location http header
var response = Request.CreateResponse(HttpStatusCode.Created, agent);
string uri = Url.Link("GetAgent", new { id = agent.AgentId});
response.Headers.Location = new Uri(uri);
return response;
}
}
}
}
throw new HttpResponseException(Request.CreateErrorResponse(
HttpStatusCode.BadRequest, "Could not deserialize agent"));
}
and this is my js
var ViewModel = function() {
var self = this;
self.agents = ko.observableArray();
self.error = ko.observable();
self.agent = ko.observableArray();
self.newAgent = {
FirstName: ko.observable(),
LastName: ko.observable(),
CodeName: ko.observable(),
Description: ko.observable(),
ImagePath: ko.observable()
}
var agentsUrl = "/api/agents/";
function ajaxHelper(uri, method, data) {
self.error(""); // Clear error message
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 getAllAgents() {
ajaxHelper(agentsUrl, "GET").done(function (data) {
self.agents(data);
});
}
self.addAgent = function (formElement) {
var agent = {
AgentId: self.newAgent.Agent().AgentId,
FirstName: self.newAgent.FirstName(),
LastName: self.newAgent.LastName(),
CodeName: self.newAgent.CodeName(),
Description: self.newAgent.Description(),
ImagePath: self.newAgent.ImagePath()
};
ajaxHelper(agentsUrl, 'POST', agent).done(function (item) {
self.agents.push(item);
});
}
getAllAgents();
};
ko.applyBindings(new ViewModel());
and this is my image element
<img data-bind="attr:{ src: ImagePath }"/>
but the image is not displaying and i can't figure out to add an upload,
please someone help , i don't need angular , just a simple mvvm such as knockout js but am relative new in it.
Look at the generated <img> element with Chrome console, or Firebug from firefox (specially the src property). Then copy the URL in a new tab and check if its displayed. I think your problem is that the element is rendered correctly, but your project cannot render direct images, as MVC will try to use the route logic to find the controller/action you are requesting, returning an HTTP 404. Check this response for a solution
You can create a simple form to upload files, or perhaps you can use jquery $.post, if you want to use ajax. Here is a sample for that
function myItemsViewModel(ItemID, GroupID, ItemName, Quantity) {
this.ItemID = ItemID;
this.GroupID = GroupID;
this.ItemName = ItemName;
this.Quantity = Quantity;
}
And i have below code for posting to the controller
var CreateRecord = function () {
var Name = $.trim($("#divCreate").find("#txtName").val());
var Department = $.trim($("#divCreate").find("#txtDepartment").val());
var ItemsList = [];
$('#myDynamicTable').find('tr').each(function () {
var row = $(this);
var itemName = $.trim(row.find(".itemName input").val());
var itemQty = $.trim(row.find(".itemQty input").val());
var myItems = new myItemsViewModel("", "", itemName, itemQty);
ItemsList.push(myItems);
});
var obj = new myRecordEntryViewModel("", Name, Department, ItemsList);
var viewmodel = JSON.stringify(obj);
$.ajax({
type: 'POST',
cache: false,
dataType: 'html',
data: viewmodel,
headers: GetRequestVerificationToken(),
contentType: 'application/json; charset=utf-8',
url: '/' + virtualDirectory + '/RecordEntry/Save',
success: function (data) {
$("#divMaster").html(data);
return false;
},
error: function (msg) {
alert("Error Submitting Record Request!");
}
});
}
At the line var viewmodel = JSON.stringify(obj);, viewmodel has all the values that i want in my ItemsList array variable.
Problem is my ItemsList array is coming as null in the controller. Name and Department are coming through with the correct passed values.
Below is my controller code.
Class
public class myRecordEntryViewModel
{
public long ID { get; set; }
public string Name { get; set; }
public string Department { get; set; }
public string[] ItemsList { get; set; }
}
Save action
[ActionName("Save")]
[NoCache]
public ActionResult Save(myRecordEntryViewModel viewModel)
{
//here viewModel.ItemsList is null, what could i be missing
if (this.SaveEntry(viewModel.Name,viewModel.Department,viewModel.ItemsList))
{
}
return this.View();
}
I'm wondering why viewModel.ItemsList is coming as null in controller yet it has values during the post from jQuery.
You should create a class for the Item in Item List (In C#)
public class Item {
public string ItemName { get; set; }
public int Quantity { get; set; }
}
And then change the viewmodel class
public class myRecordEntryViewModel
{
public long ID { get; set; }
public string Name { get; set; }
public string Department { get; set; }
//public string[] ItemsList { get; set; }
public List<Item> ItemsList {get ; set;}
}
The controller can not map the Item List from your request into model because one is a list of string and other is a list of object.
There are several problems in your codes...
1) ItemList in your class and your javascript code are not same - The frist one is an array of strings, and the second is an array of objects
2) In your action method, you should change parameter type like the following:
public ActionResult Save(string viewModel)
3) In the body of your action method, you should deserialize the json string (viewModel) and make the model object from it. The following is an example...
https://stackoverflow.com/a/17741421/1814343
Try the below code and see if your model gets the values.
Let me know if you face any problems, because I've already implemented this in one of my projects
var CreateRecord = function () {
var Name = $.trim($("#divCreate").find("#txtName").val());
var Department = $.trim($("#divCreate").find("#txtDepartment").val());
var model="";
var ItemsList = [];
$('#myDynamicTable').find('tr').each(function () {
var row = $(this);
var itemName = $.trim(row.find(".itemName input").val());
var itemQty = $.trim(row.find(".itemQty input").val());
var myItems = new myItemsViewModel("", "", itemName, itemQty);
ItemsList.push(myItems);
});
model = ['Name' : Name , 'Department' : Department , 'ItemsList' :ItemsList];
$.ajax({
type: 'POST',
cache: false,
dataType: 'html',
data: JSON.stringify(model),
headers: GetRequestVerificationToken(),
contentType: 'application/json; charset=utf-8',
url: '/' + virtualDirectory + '/RecordEntry/Save',
success: function (data) {
$("#divMaster").html(data);
HideLoader();
return false;
},
error: function (msg) {
alert("Error Submitting Record Request!");
HideLoader();
}
});
}
Just don't get it what i'm doing wrong..
i've been looking for dozens of similar questions, yet still got misunderstandings...
when i call CallHandler function from JS, i always get 'Request Failed' alert.
please help me.
JS/Jquery:
function CallHandler() {
$.ajax({
url: "DemoHandler.ashx",
contentType: "application/json; charset=utf-8",
type: 'POST',
dataType: "json",
data: [{"id": "10000", "name": "bill"},{"id": "10005", "name": "paul"}],
success: OnComplete,
error: OnFail
});
return false;
}
function OnComplete(result) {
alert(result);
}
function OnFail(result) {
alert('Request Failed');
}
asp.net c# code behind:
public void ProcessRequest(HttpContext context)
{
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
string jsonString = HttpContext.Current.Request.Form["json"];
List<Employee> emplList = new List<Employee>();
emplList = jsonSerializer.Deserialize<List<Employee>>(jsonString);
string resp = "";
foreach (Employee emp in emplList){
resp += emp.name + " \\ ";
}
context.Response.Write(resp);
}
public class Employee
{
public string id { get; set; }
public string name { get; set; }
}
Try
data: JSON.stringify([{id: "10000", name: "bill"},{id: "10005", name: "paul"}])
edit I removed the quotes from the property names
Also, the JSON string needs to be read in other way
string jsonString = String.Empty;
HttpContext.Current.Request.InputStream.Position = 0;
using (StreamReader inputStream = new StreamReader(HttpContext.Current.Request.InputStream))
{
jsonString = inputStream.ReadToEnd();
}
An working solution
public void ProcessRequest(HttpContext context)
{
var jsonSerializer = new JavaScriptSerializer();
var jsonString = String.Empty;
context.Request.InputStream.Position = 0;
using (var inputStream = new StreamReader(context.Request.InputStream))
{
jsonString = inputStream.ReadToEnd();
}
var emplList = jsonSerializer.Deserialize<List<Employee>>(jsonString);
var resp = String.Empty;
foreach (var emp in emplList)
{
resp += emp.name + " \\ ";
}
context.Response.ContentType = "application/json";
context.Response.ContentEncoding = Encoding.UTF8;
context.Response.Write(jsonSerializer.Serialize(resp));
}
public class Employee
{
public string id { get; set; }
public string name { get; set; }
}
public bool IsReusable
{
get
{
return false;
}
}