select2 sending null params to controller - c#

I'm trying to use select2 multiselect with an ajax call to retrieve the data and filter based on user input, but when it hits the controller the params are null. Unfortunately (I think because it's custom select2 api) I can't put a chrome breakpoint in the ajax call to mess with it, but the URL looks fine on the network tab. Right now the ajax calls are written slightly differently, bc I've been trying different solutions; neither work.
I also tried this post, which he said worked, but no dice for me:
jquery-select2 always sends null params in controller
$(".filter-agencies").select2({
//data: agencies,
ajax: {
cache: false,
datatype: 'JSON',
type: 'GET',
url: 'Home/GetFilterAgency',
data: function (params) {
return {q:params}
},
processResults: function (data) {
return {
results: data
}
}
},
placeholder: 'Agencies',
width: '150',
multiple: true,
closeOnSelect: false,
minimumInputLength: 4
////tags: true
});
$(".filter-advertisers").select2({
//data: filterSelect,
ajax: {
url: 'Home/GetFilterAdvertiser',
data: function (params) {
var query = {
search: params.term
}
return query
},
processResults: function (data) {
//advertisers = $.map(data, function (obj) {
// obj = { id: i, text: obj }
// i = i + 1;
// return obj
//})
return {
results: data
}
}
},
placeholder: 'Advertisers',
closeOnSelect: false,
minimumInputLength: 4,
allowClear: true,
width: '150',
multiple: true
});
[HttpGet]
public string GetFilterAdvertiser(string query)
{
var x = _orderedLinesProcessor.GetFilterAdvertiser();
var i = 0;
var dict = new Dictionary<int, string>();
foreach (var el in x)
{
dict.Add(i, el);
i += 1;
}
return JsonConvert.SerializeObject(dict);
}

Change query to search in controller:
public string GetFilterAdvertiser(string search)

Related

How to display viewbag on view on HttpPost

I want to be able to display the ViewBag on view on button click event, this is my code:
[HttpPost]
public ActionResult SpecificWorkflowReport(Report2ListViewModel wf)
{
var getSpRecord = db.Mworkflow().ToList();
var getRecord = (from u in getSpRecord
select new Report2ListViewModel
{
WorkFlowType = u.WorkFlowType,
WorkflowInstanceId = u.WorkflowInst,
WorkFlowDescription = u.WorkFlowDesc,
}).ToList();
ViewBag.WorkflowType = wf.WorkFlowType;
ViewBag.WorkflowInstanceId = wf.WorkflowInst;
ViewBag.WorkFlowDescription = wf.WorkFlowDesc
var data = Newtonsoft.Json.JsonConvert.SerializeObject(getRecord);
return Json(data);
}
i have tried this:
Worflow Type: #ViewBag.WorkflowType
Workflow Instance Id: #ViewBag.WorkflowInstanceId
Workflow Description: #ViewBag.WorkFlowDescription
My Javascript and json Call:
<script type="text/javascript">
$(function () {
var table = $("#reportTable").DataTable();
var url = $("#frmSpecificWorkflowReport").attr('action');
var str = $("#frmSpecificWorkflowReport").serialize();
$.ajax({
url: url,
type: "POST",
data: str,
cache: false,
dataType: "json",
success: function (_data) {
if (_data.f !== undefined) {
swal({
title: "Empty Result Set",
text: "No record found",
type: "info"
});
table.clear();
return false;
}
var arr = $.map(JSON.parse(_data), function (el) { return el
});
if (arr.length === 0) {
swal({
title: "Empty Result Set",
text: "No record found",
type: "info"
});
}
table.clear();
table.destroy();
$('#reportTable').dataTable({
data: arr,
columns: [
{ "data": "WorkFlowType" },
{ "data": "WorkflowInstanceId" },
{ "data": "WorkFlowDescription" },
],
dom: 'Bfrtip',
buttons: [
'copy', 'csv', 'excel',
{
extend: 'pdfHtml5',
orientation: 'landscape',
pageSize: 'LEGAL'
}
]
});
table = $("#reportTable").DataTable();
but the ViewBag values are always null on the view, any assistance will be appreciated. I just added Javascript and json call to the post, i want to be able to retrieve my stored data and display it anywhere on the view
#UwakPeter your code snippets is ok, but you are returning Json, may be you are calling this method via javascript, so the view is not updating, you need to reload the view, by the submit button.
If you are using javascript, you can pass your data list and model data as anonymous object, so that you don't need to use ViewBag. in client side by ajax success function you can grab them (WorkflowType, WorkflowInstanceId, WorkFlowDescription, Result)
[HttpPost]
public ActionResult SpecificWorkflowReport(Report2ListViewModel wf)
{
var getSpRecord = db.Mworkflow().ToList();
var getRecord = (from u in getSpRecord
select new Report2ListViewModel
{
WorkFlowType = u.WorkFlowType,
WorkflowInstanceId = u.WorkflowInst,
WorkFlowDescription = u.WorkFlowDesc,
}).ToList();
var data = Newtonsoft.Json.JsonConvert.SerializeObject(getRecord);
return Json(new{
WorkflowType = wf.WorkFlowType,
WorkflowInstanceId = wf.WorkflowInst,
WorkFlowDescription = wf.WorkFlowDesc,
Result= data
}, JsonRequestBehaviour.AllowGet);
}
JS
$.ajax({
url: url,
type: "POST",
data: str,
cache: false,
dataType: "json",
success: function (_data) {
var workflowType=_data.WorkflowType; //set it to HTML control
var workflowInstanceId =_data.WorkflowInstanceId;
var workFlowDescription = _data.WorkFlowDescription;
$('#reportTable').dataTable({
data: _data.Result
});
}
)};
Try this,
#{
Layout = null;
ProjectMVC.Models.Record record= (ProjectMVC.Models.Record)ViewBag.Recorddetails;
}
...
Worflow Type: #record.WorkflowType

Web API ActionFilterAttribute won't return a status when AJAX call triggers response

I'm making a Select2 call from an MVC view using the following code:
ajax: {
url: url,
delay: 150,
data: function (params) {
return GMK_Select2QueryData(params, 30, additionalData);
},
processResults: function (data, params) {
var resultsArr = [];
for (var i = 0; i < data.items.length; i++) {
resultsArr.push({
id: data.items[i].id,
text: data.items[i].text,
description: data.items[i].description,
data: data.items[i].data
});
}
return {
results: resultsArr,
pagination: {
more: data.more
}
};
},
error: function(jqXHR, textStatus, errorThrown) {
alert(jqXHR.status);
},
cache: false
}
I'm attempting to capture whether a session has timed out, then return the status code to the "error" function so that I can pop something up on the screen stating they need to log back in. Right now, I'm simply alerting to the screen for testing purposes.
I'm using a Web API ActionFilterAttribute, but when I create an error response, the jqXHR is always status = 0 no matter what I do.
public class SessionActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext filterContext)
{
HttpContext ctx = HttpContext.Current;
if (ctx.Session == null || ctx.Session["user"] == null)
{
filterContext.Response = filterContext.Request.CreateErrorResponse(HttpStatusCode.RequestTimeout, "Session Timeout");
}
base.OnActionExecuting(filterContext);
}
}
SessionActionFilter Action filter is perfect. No problem in filter
Please update Select2 call as follows:-
Answer 1:-
ajax: {
url: url,
delay: 150,
data: function (params) {
return GMK_Select2QueryData(params, 30, additionalData);
},
processResults: function (data, params) {
var resultsArr = [];
for (var i = 0; i < data.items.length; i++) {
resultsArr.push({
id: data.items[i].id,
text: data.items[i].text,
description: data.items[i].description,
data: data.items[i].data
});
}
return {
results: resultsArr,
pagination: {
more: data.more
}
};
},
params: {
error: function (jqXHR, textStatus, errorThrown) {
alert(jqXHR.status);
}
},
cache: false
}
Can get error in following ways
Using the transport option will cause select2 to break if you just want to handle response errors like in the example below.
transport: {
return $.ajax().error(function() {
alert("error fetching data");
});
}
There is another, much simpler way to handle errors. That is by using the params option like the example below.
params: {
error: function(response) {
alert("error fetching data");
}
}
Hope it helps.
Please reference select2
Another Answer
In Select2.js file add extension of "error"
serach for text "$.extend(params"
Then update extension by following code
$.extend(params, {
url: url,
dataType: options.dataType,
data: data,
success: function (data) {
if (requestNumber < requestSequence) {
return;
}
// TODO - replace query.page with query so users have access to term, page, etc.
var results = options.results(data, query.page);
query.callback(results);
},
/* BEGIN added code */
error: function (jqXHR, status, error) {
if (requestNumber < requestSequence) {
return;
}
var r = null;
if (options.error) {
r = options.error(jqXHR, status, error);
}
query.callback(r || { results: [] });
} /* END added code */
});
And your updated ajax call
ajax: {
url: url,
delay: 150,
data: function (params) {
return GMK_Select2QueryData(params, 30, additionalData);
},
processResults: function (data, params) {
var resultsArr = [];
for (var i = 0; i < data.items.length; i++) {
resultsArr.push({
id: data.items[i].id,
text: data.items[i].text,
description: data.items[i].description,
data: data.items[i].data
});
}
return {
results: resultsArr,
pagination: {
more: data.more
}
};
},
error: function (jqXHR, status, error) {
alert(error + ": " + jqXHR.responseText + ": " + jqXHR.status);
},
cache: false
}

Sending object to a controller in asp.net mvc using ajax

I have issue with sending object contains array to a controller
this is my js code
var messageId = 0;
function DraftMessage()
{
var to = [];
var i = 0;
$('#to option:selected').each(function (index, element) {
to[i++] = $(element).val();
});
console.log(to);
$.ajax({
type: "POST",
url: "#Url.Action("DraftMessage", "Activities")",
datatype: "json",
traditional: true,
async: false,
data: { "id": messageId, "To": to, "Title": $("#title").val(), "Project": $("#project").val(), "AreaId": $("#areaId").val(), "Body": $("#messageBody").val() },
beforeSend: function () { }
}).done(function (Id) {
console.log(Id);
messageId = Id;
});
}
$("input, select, textarea").change(function () { DraftMessage(); });
var contents = $('.note-editable').html();
$(".compose-message").on("blur", ".note-editable", function () {
if (contents != $(this).html()) {
DraftMessage();
contents = $(this).html();
}
});
and this is my controller side
public int DraftMessage(message draftMessage, HttpPostedFileBase[] files = null)
{
return new MessageActions().DraftMessage(draftMessage);
}
my issue is that the ajax request always send the to array as null, I do not know what is wrong so could anyone help me to resolve this issue.
Can you change your request and use
dataType: "json",
contentType: "application/json;charset=utf-8",
This should work. Please let me know.
Try this. Push your object to array and send it as Json.
array.push({yourobject datas here})
$.ajax({
type: "POST",
url: '/DraftMessage/Activities',
contentType: 'application/json',
data: JSON.stringify(array),
success: function (d) {
..
},
error: function (xhr, textStatus, errorThrown) {
console.log(errorThrown);
}
});
Convert your controller function's return type to JSonResult.
Hope helps.
do you want upload file using ajax ?!!
use the normal usage of form not the Ajax.BeginForm then in form submit event
write your code like this:
$('#Form').submit(function () {
var xhr = new XMLHttpRequest();
var fd = new FormData();
var file = $('#Image').val();
if (file) {
var fname = $('#Image')[0].files[0].name;
if (CheckFile(file)) {
var uploadFile = document.getElementById('Image').files[0];
var myArray = [];
myArray.push(uploadFile);
if (myArray.length > 0) {
for (var i = 0; i < myArray.length; i = i + 1) {
fd.append("File1", myArray[i]);
}
}
}
else {
return false;
}
}
fd.append("ID", messageId);
fd.append("Title", $('#Title').val());
fd.append("Project", $('#Project').val());
fd.append("AreaId", $('#AreaId').val());
fd.append("Body", $('#messageBody').val());
var form = $('#Form');
var token = $('input[name="__RequestVerificationToken"]', form).val();
fd.append("__RequestVerificationToken", token);
xhr.open("POST", "/ControllerName/Action/", true);
xhr.send(fd);
xhr.addEventListener("load", function (event) {
if (event.target.response != "OK") {
OnFail(event.target.response);
}
else {
OnSuccess(event);
}
}, false);
return false;
})
server side in controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult actionName(Model pModel){
HttpPostedFileBase File = Request.Files["File1"];
if (File != null && File.ContentLength != 0){
//do what you want
return Content("OK");
}
else{
Response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest;
return Content("Error Messages", System.Net.Mime.MediaTypeNames.Text.Plain);
}
}
You can try a different approach. You can serialize your entire form by doing something like this:
var formdata = $("#frmEmailInfo").serialize();
and then post it to the Controller:
$.ajax(
{
type: "POST",
data: formdata,
dataType: 'json',...

Typeahead.js and Bloodhound.js integration with C# WebForms WebMethod

I'm trying to implement a simple WebMethod in C# to search a db of 50,000 people. I'm using Twitter Bootstrap bloodhound.js and typeahead.js to tokenize and autocomplete the responses.
When I run this code, typeahead shows a dropdown menu with undefined.
How can I correctly process the JSON response to strip out the d object returned by .NET WebMethod and correctly pass my records to Bloodhound? I've tried this using the dataFilter method provided by jQuery's $.ajax, but it's not working for me.
C# WebMethod:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public static object searchStaffByName(string q)
{
using (App_Data.DQDBDataContext dc = new App_Data.DQDBDataContext())
{
var results = dc.getStaffDetails(q).ToList();
return new { Status = "OK", Records = results, Count = results.Count };
}
}
Typeahead JS implementation:
var textlookup = new Bloodhound({
datumTokenizer: function (d) {
return Bloodhound.tokenizers.whitespace(d.val);
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: 'Search.aspx/searchStaffByName',
replace: function (url, query) {
searchQuery = query;
return url;
},
ajax: {
beforeSend: function (jqXhr, settings) {
settings.data = JSON.stringify({
q: searchQuery
});
jqXhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
},
dataFilter: function (data, type) {
if (type === "json") {
data = $.parseJSON(data);
if (typeof data.d === 'object' && data.d.Count > 0) {
return data.d.Records;
}
}
},
type: 'POST'
}
}
});
textlookup.initialize();
$('.autocomplete').typeahead({
hint: true,
highlight: true,
minLength: 3
},
{
name: 'textlookup',
displayKey: 'Forename',
source: textlookup.ttAdapter()
});
Sample JSON Response:
{
"d": {
"Status":"OK",
"Records": [{
"id":45711192,
"phone":"514-579-5721",
"Forename":"Jayden",
"Surname":"Adams",
"DOB":"\/Date(990226800000)\/"
},
{
"id":12603644,
"phone":"333-143-9094",
"Forename":"Jake",
"Surname":"Adams",
"DOB":"\/Date(43542000000)\/"
},
{
"id":68196438,
"phone":"440-505-2403",
"Forename":"Josh",
"Surname":"Adams",
"DOB":"\/Date(-51152400000)\/"
}],
"Count":6
}
}
If your typeahead data will be in the name: 'textlookup', array, populate the array with your JSON response first. The following assumes data is the JSON.
textlookup = [];
for (var i = 0; i < data.d.Records.length; i += 1) {
textlookup.push(data.d.Records[i].Forename);
}
This should push each Forename into the array textlookup. You are getting the undefined error because you are placing objects into the array.
I spent some time on this and found that it's better to return a an string array.
Here's my web method.
[WebMethod]
public static string[] MemberLookup(string MbrFullName)
{
DataSet ds = (dataset provider goes here)
List<string> members = new List<string>();
foreach(DataRow dr in ds.Tables[0].Rows)
{ members.Add(string.Format("{0}-{1}", dr["label"].ToString(), dr["value"].ToString())); }
return members.ToArray();
}

Jquery overriding global value

I am using kendo ui and i dont want duplicate records in my database so what i am doing is using the .Save function of kendo grid to check the record and if exist then return false which is working fine but when i am returning return false then it is still saving the record.
function onSave(e) {
var currentValueForSend = $("[name=RegisterNo]").val();
alert(currentValueForSend);
$.ajax(
{
url: '/StudentTransaction/CheckRegistrationNumber',
type: "POST",
data: { 'RegisterNumber': currentValueForSend },
success: function (data) {
alert(data.CurrentRegNo);
if( data.CurrentRegNo.indexOf('true') >= 0){
alert("no duplicate records");
return false;;
}
}
});
}
i am also defining a global value to override the value but i am not able to override the value
function onSave(e) {
var status;
var currentValueForSend = $("[name=RegisterNo]").val();
alert(currentValueForSend);
$.ajax(
{
url: '/StudentTransaction/CheckRegistrationNumber',
type: "POST",
data: { 'RegisterNumber': currentValueForSend },
success: function (data) {
status = data.CurrentRegNo;
}
});
if (status.indexOf('true') >= 0)) {
e.preventDefault();
alert("Duplicates not allowed");
return false;
}
}
What i am doing wrong?
This is due to the async nature of these requests.
The sequence as described in your code is:
make the request
check if status is true
get the response
You need to use function callbacks to handle this properly. Try something like this:
function onSave (e){
var currentValueForSend = $("[name=RegisterNo]").val();
alert(currentValueForSend);
$.ajax({
url : '/StudentTransaction/CheckRegistrationNumber',
type : "POST",
data : { 'RegisterNumber': currentValueForSend },
success : afterSave
});
}
function afterSave (data){
var status = data.CurrentRegNo;
if (status.indexOf('true') >= 0)) {
e.preventDefault();
alert("Duplicates not allowed");
return false;
}
}

Categories