How to return callback json from VC Controller? - asp.net-mvc

I am using 3rd party Kendo UI in client side. it expects data from server in below format.
callback([{"TaskID":4,"OwnerID":2,"Title":"Bowling}])
I am having below code in server side
public JsonResult GetAllAppointments()
{
IEnumerable<AppointmentModel> appointmentCollection = app_repository.GetAll();
if (appointmentCollection == null)
{
return Json(appointmentCollection, JsonRequestBehavior.AllowGet);
}
return Json(appointmentCollection, JsonRequestBehavior.AllowGet);
}
But this returns just json, how to add "callback" to it?

Ideally you should get an interceptor at client side which should let you modify your response format..but since you have not provided any further details I won't be able to comment on that.
You can change your return type fron JsonResult to string and manually serialize your response.You can use Json.NET to serialize your response.
Here is a NuGet LINK for the same.
public class AppointmentModel
{
public string TaskID { get; set; }
public string OwnerID { get; set; }
public string Title { get; set; }
}
public string GetAllAppointments()
{
string responseFormat = #"callback({0})";
IEnumerable<AppointmentModel> appointmentCollection = getDummyAppoitments();
if (appointmentCollection != null)
{
string json_string = Newtonsoft.Json.JsonConvert.SerializeObject(appointmentCollection);
return string.Format(responseFormat, json_string);;
}
//no items were present so sending empty response;
return string.Format(responseFormat, "[]");;
}
private IEnumerable<AppointmentModel> getDummyAppoitments()
{
return new List<AppointmentModel>() {
new AppointmentModel()
{
TaskID = "4",
OwnerID = "2",
Title = "Bowling"
}
};
}
Check out response.
Cheers!!

Related

Syncfusion Server-Side event is not passing data

I have a Asp.Net MVC project created from Syncfusion ASP.New MVC (Essential JS 2) VS template that is using Syncfusion's Data Grid. I can get the CrudUpdate event set in CrudUrl to fire at the server, however the value returned to CrudUpdate is empty. action parameter seems correctly set.
If I cast the value as Object, I get back a not-null, but VS cannot interrogate it. My guess is some weirdness in the way the value is cast or returned.
Has anyone got a complete working sample of the Syncfusion grid using the CrudUrl method with MVC (not asp). I am also guessing I may have some dependency issue.
View
#Html.EJS().Grid("CrudUrl").DataSource(dataManager => { dataManager.Url("/TestGrid2/UrlDatasource").CrudUrl("/TestGrid2/CrudUpdate").Adaptor("UrlAdaptor"); }).Columns(col =>
{
col.Field("RowKey").IsPrimaryKey(true).Add();
col.Field("PartitionKey").Add();
col.Field("sourceResourceId").Add();
col.Field("imagesLocation").Add();
col.Field("imagesResourceGroup").Add();
col.Field("imagePrefix").Add();
col.Field("imageVersion").Add();
}).AllowPaging().Toolbar(new List<string>() { "Search", "Add", "Edit", "Delete", "Update", "Cancel" }).EditSettings(edit => { edit.AllowAdding(true).AllowEditing(true).AllowDeleting(true); }).Render()
Controller
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Script.Services;
using System.Web.Services;
using DB;
//using Microsoft.AspNetCore.Mvc;
using Syncfusion.EJ2.Base;
namespace VMSSManagmentConsole.Controllers
{
public class TestGrid2Controller : Controller
{
private ModelContainer db = new ModelContainer();
public ActionResult TestGrid2()
{
//var items = db.ManagementItems.ToList();
//ViewBag.dataSource = items;
return View();
}
public ActionResult UrlDatasource([FromBody]DataManagerRequest dm)
{
IEnumerable DataSource = db.ManagementItems.ToList();
DataOperations operation = new DataOperations();
int count = DataSource.Cast<ManagementItem>().Count();
if (dm.Skip != 0)
{
DataSource = operation.PerformSkip(DataSource, dm.Skip); //Paging
}
if (dm.Take != 0)
{
DataSource = operation.PerformTake(DataSource, dm.Take);
}
var result = (ActionResult)(dm.RequiresCounts ? Json(new { result = DataSource, count = count }) : Json(DataSource));
return result;
}
public ActionResult CrudUpdate([FromBody]ICRUDModel<ManagementItem> value, string action)
{
//if (value.action == "update")
//{
// var ord = value.value;
// ManagementItem val = db.ManagementItems.Where(or => or.RowKey == ord.RowKey).FirstOrDefault();
// val.imagePrefix = ord.imagePrefix;
// val.imagesLocation = ord.imagesLocation;
// val.imagesResourceGroup = ord.imagesResourceGroup;
// val.imageVersion = ord.imageVersion;
// val.sourceResourceId = ord.sourceResourceId;
//}
//else if (value.action == "insert")
//{
// db.ManagementItems.Add(value.value);
//}
//else if (value.action == "remove")
//{
// db.ManagementItems.Remove(db.ManagementItems.Where(or => or.RowKey == value.key.ToString()).FirstOrDefault());
// return Json(value);
//}
//return Json(value.value);
return null;
}
public class ICRUDModel<T> where T : class
{
public string action { get; set; }
public string table { get; set; }
public string keyColumn { get; set; }
public object key { get; set; }
public T value { get; set; }
public List<T> added { get; set; }
public List<T> changed { get; set; }
public List<T> deleted { get; set; }
public IDictionary<string, object> #params { get; set; }
}
}
}
Use the DataGrid scaffold wizard. On the third page select DataSourceType = "Remote Data". A page and controller will be created with the correct code.
For your reference, we have created a sample and perform CRUD actions. Please refer the attached sample for more information.
Sample: https://www.syncfusion.com/downloads/support/directtrac/general/ze/GridEJ2Mvc-914352281
The reported problem occurred when model mismatched. For Example, when we specify the number column field(EmployeeID) in grid but while inserting you did not specify the value for that column then it shows value as null in CrudUpdate, for this scenario you need to specify the nullable value for that field in model class as follows.
public class OrdersDetails
{
public OrdersDetails(int OrderID, string CustomerId, int EmployeeId, double Freight, bool Verified, DateTime OrderDate, string ShipCity, string ShipName, string ShipCountry, DateTime ShippedDate, string ShipAddress)
{
this.OrderID = OrderID;
this.CustomerID = CustomerId;
this.EmployeeID = EmployeeId;
. . . . .
}
public static List<OrdersDetails> GetAllRecords()
{
if (order.Count() == 0)
{
int code = 10000;
for (int i = 1; i < 10; i++)
{
order.Add(new OrdersDetails(code + 1, "ALFKI", i + 0, 2.3 * i, false, new DateTime(1991, 05, 15), "Berlin", "Simons bistro", "Denmark", new DateTime(1996, 7, 16), "Kirchgasse 6"));
. . . . .
}
}
return order;
}
public int? OrderID { get; set; }
public string CustomerID { get; set; }
public int? EmployeeID { get; set; } // it accept null value
. . . . .
}
}
If you still face the problem then share more details or below information that will helpful for us to validate further and provide a better solution as soon as possible.
• Did the problem occurred for both update and insert?
• Share package version details.
Regards,
Thavasianand S.

Jquery post to mvc 4 controller not passing data

I'm trying to pass data from JQuery to an MVC 4 controller. The controller gets invoked, but no data is passed. In the past I always just used form serialization, but that's not appropriate here.
My Controller:
[HttpPost]
public ActionResult Write(VideoSessionEnvelope envelope)
{
if (ModelState.IsValid)
{
envelope = Log.Write(envelope);
}
var result = Json(envelope);
return result;
}
We use an envelope class as a container for all view models
public class VideoSessionEnvelope : BaseEnvelope
{
public VideoSessionEnvelope()
{
SessionStart = new VideoSessionStartViewModel();
}
public Guid? LogEntryID { get; set; }
public VideoSessionStartViewModel SessionStart { get; set; }
}
}
The view model
public class VideoSessionStartViewModel: IViewModel
{
public string SessionId { get; set; }
public int UserId { get; set; }
public string Message { get; set; }
}
And finally the javascript
var Logging = Logging || {};
Logging.VideoSession = function () {
var Start = function (sessionId, userId, message) {
var envelope = {
SessionStart: {
"SessionId": sessionId,
"UserId": userId,
"Message": message
}
}
var data = JSON.stringify(envelope);
$.ajax({
type: "POST",
url: "/Logging/Write",
data: data,
datatype: "application/json",
success: function (result) {
return result;
},
error: function (request, status, error) {
return error;
}
});
};
return {
Start: Start
};
}();
According to Firebug the data is passed as
JSON
SessionStart Object { SessionId="sessionIdVal", UserId=123, Message="messageValue"}
Message "messageValue"
SessionId "sessionIdVal"
UserId 123
The controller gets called, but the properties in the view model are always null. I've tried several variations on the theme, nothing seems to work.
Try wrapping your data in a literal with the name as envelope so it will be picked up by the Model Binder:
data: { envelope: data },
UPDATE
Remove the call to JSON.stringify(), it is not strictly necessary to serialize the object literal.

uCommerce - add dynamic property to order line

I have hit a problem building a uCommerce site based on top of the demo razor store available http://thesitedoctor.co.uk/portfolio/avenue-clothingcom/
The demo uses servicestack and the ucommerceapi for its basket functions.
I am trying to add a dynamic property to the basket (on an order line) at the point where the user clicks buy. I traced through the productpage.js file and amended the code to add a new property ('message'):
function (data) {
var variant = data.Variant;
$.uCommerce.addToBasket(
{
sku: variant.Sku,
variantSku: variant.VariantSku,
quantity: qty,
message: $('#personalisedMessage').val()
},
function () {
updateCartTotals(addToCartButton);
}
);
});
using firebug, i checked the data that is being posted
addToExistingLine: true
message: "this is a message"
quantity:"1"
sku: "Product (options: none)"
variantSku:""
Posting this does not cause an error, but I cannot tell if it has worked either - I cannot find it in the database, assuming that it would be stored in OrderProperty table. In this scenario, I am 'buying' a product with no variations.
Any help is greatly appreciated with this.
Out of the box you can't add order/line item properties via the API like that. The API payload that you've added to is specified although valid JSON won't get interpreted/used by the API.
Instead what you'll need to do is add your own method to the API. To do this you'll need to implement a service from IUCommerceApiService and then you can do what you need. I've created an example (untested) below and will get it added to the demo store as I think it's a useful bit of functionality to have.
public class AddOrderLineProperty
{
public int? OrderLineId { get; set; }
public string Sku { get; set; }
public string VariantSku { get; set; }
public string Key { get; set; }
public string Value { get; set; }
}
public class AddOrderLinePropertyResponse : IHasResponseStatus
{
public AddOrderLinePropertyResponse() { }
public AddOrderLinePropertyResponse(UCommerce.EntitiesV2.OrderLine line)
{
if (line == null)
{
UpdatedLine = new LineItem();
return;
}
var currency = SiteContext.Current.CatalogContext.CurrentCatalog.PriceGroup.Currency;
var lineTotal = new Money(line.Total.Value, currency);
UpdatedLine = new LineItem()
{
OrderLineId = line.OrderLineId,
Quantity = line.Quantity,
Sku = line.Sku,
VariantSku = line.VariantSku,
Price = line.Price,
ProductName = line.ProductName,
Total = line.Total,
FormattedTotal = lineTotal.ToString(),
UnitDiscount = line.UnitDiscount,
VAT = line.VAT,
VATRate = line.VATRate
};
}
public ResponseStatus ResponseStatus { get; set; }
public LineItem UpdatedLine { get; set; }
}
public class AddOrderLinePropertyService : ServiceBase<AddOrderLineProperty>, IUCommerceApiService
{
protected override object Run(AddOrderLineProperty request)
{
var orderLineId = request.OrderLineId;
var sku = request.Sku;
var variantSku = request.VariantSku;
var orderLine = findOrderLine(orderLineId, sku, variantSku);
addPropertyToOrderLine(orderLine, request.Key, request.Value);
TransactionLibrary.ExecuteBasketPipeline();
var newLine = findOrderLine(orderLineId, sku, variantSku);
return new AddOrderLinePropertyResponse(newLine);
}
private void addPropertyToOrderLine(OrderLine orderLine, string key, string value)
{
if (orderLine == null)
return;
orderLine[key] = value;
orderLine.Save();
}
private static OrderLine findOrderLine(int? orderLineId, string sku, string variantSku)
{
return orderLineId.HasValue
? getOrderLineByOrderLineId(orderLineId)
: getOrderLineBySku(sku, variantSku);
}
private static OrderLine getOrderLineBySku(string sku, string variantSku)
{
return String.IsNullOrWhiteSpace(variantSku)
? getOrderLines().FirstOrDefault(l => (l.Sku == sku))
: getOrderLines().FirstOrDefault(l => (l.Sku == sku && l.VariantSku == variantSku));
}
private static OrderLine getOrderLineByOrderLineId(int? orderLineId)
{
return getOrderLines().FirstOrDefault(l => l.OrderLineId == orderLineId);
}
private static ICollection<OrderLine> getOrderLines()
{
return TransactionLibrary.GetBasket().PurchaseOrder.OrderLines;
}
}
You'll need to add the new method to uCommerce.jQuery.js as well something like this:
addOrderLineProperty: function (options, onSuccess, onError) {
var defaults = {
orderLineId: 0
};
var extendedOptions = $.extend(defaults, options);
callServiceStack({ AddOrderLineProperty: extendedOptions }, onSuccess, onError);
}
Let me know if you have any issues using it.
Tim

How do I send deep JSON objects to an Action?

In my web app I have a dynamically generated form that I use to create a JSON object to pitch back to an Action. As seen here:
function getConfigItemWithValidators() {
log.info("getConfigItemWithValidators()");
var oConfigItem = {
"Name": $("#txtName").html(),
"InputFileCellIndex": $("#inpFieldIndex").val(),
"Validators": new Array() };
for (var i = 0; true; i++) {
var oHiddenValidatorName = $("[name=hidVld"+i+"]");
var oHiddenValidatorVal = $("[name=txtVld"+i+"]");
if ($("[name=hidVld" + i + "]").length > 0) {
var oValidator = {
"ValidationType": oHiddenValidatorName.val(),
"ValidationValue": oHiddenValidatorVal.val() };
oConfigItem.Validators.push(oValidator);
}
else
break;
}
return oConfigItem
}
function saveConfigItemChanges() {
log.info("saveConfigItemChanges()");
var oConfigItem = getConfigItemWithValidators();
$("#divRulesContainer").hide("normal");
$.getJSON("PutValidationRules", oConfigItem,
saveConfigItemChangesCallback);
}
In my action, while debugging, I notice that model.Validators is empty:
[AcceptVerbs(HttpVerbs.Get)]
public JsonResult PutValidationRules(ConfigItem model)
{
// model.Validators is empty
return Json(true);
}
Here is the code to ConfigItem:
public class ConfigItem
{
public string Name { get; set; }
public int InputFileCellIndex { get; set; }
private IList<Validator> _validators = new List<Validator>();
public IList<Validator> Validators
{
get
{
return _validators;
}
}
public void AddValidator(Validator aValidator)
{
aValidator.ConfigItem = this;
_validators.Add(aValidator);
}
}
Is there something I need to do to get ConfigItem.Validators to get built for my JSON requests?
It is empty because default binder does not work for arrays very well. You will need to implement a custombinder.
You can see here an example of custombinders

How to get list of customers, jobs, and employeers using Quickbooks QBFC (8.0 SDK)

I have been given the painful task of writing a C# application to sync up employee time entries in a separate database with Quickbooks. Since I'm brand new to QB programming, I'm trying to peform basic tasks, such as getting a list of customers, then jobs for each customer, then employees. I've been reading the SDK documentation, but I'm still a little fuzzy on the details because the examples I'm finding are a little too advanced for me at the moment :-P
To keep things simple, I would like to ask for a code snippet that gives me the list of customers for starters. Here's the code I've got:
QBSessionManager SessionManager = new QBSessionManager();
IMsgSetRequest customerSet = SessionManager.CreateMsgSetRequest("US", 8, 0);
//
// Code to get list of customers here.
//
SessionManager.OpenConnection2("", "New App", ENConnectionType.ctLocalQBD);
SessionManager.BeginSession(string.Empty, ENOpenMode.omDontCare);
IMsgSetResponse Resp = SessionManager.DoRequests(customerSet);
MessageBox.Show(Resp.ToXMLString());
SessionManager.EndSession();
SessionManager.CloseConnection();
Can anyone fill in the "code to get list of customers here" for me? Thank you very much in advance!
Victor
customers.IncludeRetElementList.Add("IsActive");
customers.IncludeRetElementList.Add("ListID");
customers.IncludeRetElementList.Add("EditSequence");
customers.IncludeRetElementList.Add("Name");
customers.IncludeRetElementList.Add("ParentRef");
Only the fields specified in the above list will be returned from QuickBooks - it is very important to use the correct strings in the correct case - no error messages will result if something is wrong. You cannot specify sub-fields (eg, City within an Address block; you must get the entire Address block). For custom fields, you also must specify the OwnerID (use 0 for custom fields that are not private to an application)
customers.IncludeRetElementList.Add("DataExtRet"); //will return non-private and/or private data extension fields depending on the OwnerIDList, below
customers.OwnerIDList.Add("0"); // required for non-private data extn fields
customers.OwnerIDList.Add("Your Appln GUID"); // Use this to get private data extns for the Appln identified by the GUID
Ok, seems like I found the missing piece:
ICustomerQuery customers = customerSet.AppendCustomerQueryRq();
This produces all the data related to each customer, which is a step forward. Parsing the XML for customers should be pretty straightforward, but parsing the individual tasks/jobs for each customer will be laborious, because there are no subnodes for each task - basically you get repeating chunks of XML with all the basic customer info (address, billing address, shipping address, etc.), then this one property called "FullName" which appends a colon to the customer name, followed by the task title (which itself can be followed by another colon with a subtask title, etc.). I'm wondering if there's something clever I can do with the request query to get a better xml response (for instance, specify what properties I want returned, and maybe enforce the creation of subnodes for each task for a given customer)...comments are appreciated.
Adding to Victors, Chili and Hassan's answer. Glad to have stumbled on this question as I myself was struggling with the QBFC examples.
Here is a full set of code that might just help someone down the road. If in the meantime someone could just point me in the direction of some useful documentation...that would be great.
Getting the Employee data to an XML string
public static string EmployeeListXML()
{
QBSessionManager SessionManager = new QBSessionManager();
IMsgSetRequest msgSetReq = SessionManager.CreateMsgSetRequest("US", 8, 0);
IEmployeeQuery employee = msgSetReq.AppendEmployeeQueryRq();
employee.IncludeRetElementList.Add("IsActive");
employee.IncludeRetElementList.Add("ListID");
employee.IncludeRetElementList.Add("EditSequence");
employee.IncludeRetElementList.Add("FirstName");
employee.IncludeRetElementList.Add("LastName");
employee.IncludeRetElementList.Add("SSN");
//employee.IncludeRetElementList.Add("ParentRef");
//employee.IncludeRetElementList.Add("DataExtRet"); //will return non-private and/or private data extension fields depending on the OwnerIDList, below
employee.OwnerIDList.Add("0"); // required for non-private data extn fields
//customers.OwnerIDList.Add("Your Appln GUID"); // Use this to get private data extns for the Appln identified by the GUID
SessionManager.OpenConnection2("", Application.ProductName, ENConnectionType.ctLocalQBD);
//SessionManager.BeginSession(string.Empty, ENOpenMode.omDontCare);
SessionManager.BeginSession(frmMain.QBFileName, ENOpenMode.omDontCare); // I have the filename on frmMain
IMsgSetResponse Resp = SessionManager.DoRequests(msgSetReq);
SessionManager.EndSession();
SessionManager.CloseConnection();
//MessageBox.Show(Resp.ToXMLString());
return Resp.ToXMLString();
}
Putting the XML string into a List of Emplpoyee Objects
public static List<Employee> EmployeeXMLtoList()
{
string sXML = EmployeeListXML();
List<Employee> lstEmp = new List<Employee>();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(sXML);
XmlNodeList parentNode = xmlDoc.GetElementsByTagName("EmployeeRet");
foreach (XmlNode childNode in parentNode)
{
Employee oEmp = new Employee();
oEmp.ListID = childNode.SelectSingleNode("ListID").InnerText;
oEmp.EditSequence = childNode.SelectSingleNode("EditSequence").InnerText;
oEmp.Active = childNode.SelectSingleNode("IsActive").InnerText;
oEmp.FirstName = childNode.SelectSingleNode("FirstName").InnerText;
oEmp.LastName = childNode.SelectSingleNode("LastName").InnerText;
oEmp.SSN = childNode.SelectSingleNode("SSN").InnerText;
lstEmp.Add(oEmp);
}
return lstEmp;
}
Function that return an Employee Object using Linq
public static Employee GetEmployeeObject(string sSSN)
{
Employee oReturn = null;
List<Employee> lstEmployee = EmployeeXMLtoList();
IEnumerable<Employee> lstEmps = from oEmp in lstEmployee
where oEmp.SSN == sSSN
select oEmp;
foreach (var oEmp in lstEmps)
{
oReturn = oEmp;
}
return oReturn;
}
Example of Code
Employee oEmployee = QB.GetEmployeeObject("112-35-8560");
Employee Class
public class Employee
{
private string sEmployeeID;
private string sSSN;
private string sLastName;
private string sFirstName;
private string sAddress1;
private string sAddress2;
private string sCity;
private string sState;
private string sZipCode;
private string sGender;
private string sEthnicity;
private DateTime dDOB;
private string sMaritalStatus;
private int iDependants;
private string sUScitizen;
private decimal iPayRate;
private string sPhone;
private DateTime dHireDate;
private string sEmail;
public Employee() { }
public string EmployeeID
{
get { return sEmployeeID; }
set { sEmployeeID = value; }
}
public string ListID
{
get; set;
}
public string EditSequence
{
get; set;
}
public string Active
{
get; set;
}
public string SSN
{
get { return sSSN; }
set { sSSN = value; }
}
public string LastName
{
get { return sLastName; }
set { sLastName = value; }
}
public string FirstName
{
get { return sFirstName; }
set { sFirstName = value; }
}
public string FullName
{
get { return FirstName + " " + LastName; }
set { }
}
public string Address1
{
get { return sAddress1; }
set { sAddress1 = value; }
}
public string Address2
{
get { return sAddress2; }
set { sAddress2 = value; }
}
public string State
{
get { return sState; }
set { sState = value; }
}
public string City
{
get { return sCity; }
set { sCity = value; }
}
public string ZipCode
{
get { return sZipCode; }
set { sZipCode = value; }
}
public string Gender
{
get { return sGender; }
set { sGender = value; }
}
public string Ethnicity
{
get { return sEthnicity; }
set { sEthnicity = value; }
}
public DateTime DOB
{
get { return dDOB; }
set { dDOB = value; }
}
public string MaritalStatus
{
get { return sMaritalStatus; }
set { sMaritalStatus = value; }
}
public int Dependants
{
get { return iDependants; }
set { iDependants = value; }
}
public string UScitizen
{
get { return sUScitizen; }
set { sUScitizen = value; }
}
public decimal PayRate
{
get { return iPayRate; }
set { iPayRate = value; }
}
public DateTime HireDate
{
get { return dHireDate; }
set { dHireDate = value; }
}
public string Phone
{
get { return sPhone; }
set { sPhone = value; }
}
public string Email
{
get { return sEmail; }
set { sEmail = value; }
}
}

Resources