Empty message in hi-jacked POST from javascript to C# MVC - c#

Im trying to hook myself up to a smaller website im a member in.
It has some kind of chat board based on xml which i parse and do statistics on etc.
Now i want to be able to post short summarys using their own options for posting, handled by JavaScript here (cb is chatboard number):
function CB_Post() {
jQuery.ajaxSetup({ contentType: "application/x-www-form-urlencoded;charset=utf-8" });
//alert($("#message").val());
//$("#fm").serialize()
$.post("do.aspx?do=add", { message: $("#message").val(), cb: $("#cb").val() }, function (data) {
if (data == '') {
document.getElementById("message").value = '';
FC('message', iMaxChar);
} else {
alert(data);
}
}, "text");
My implemetaiton so far is:
public void PostData(string text)
{
var data = new NameValueCollection();
data.Add("message", (#text+#"\n"));
data.Add("cb", "0");
client.Headers["contentType"] = "application/x-www-form-urlencoded;charset=utf-8";
var result = client.UploadValues("/cb/do.aspx?do=add", data);
}
This works and the message get sent, but it ends up as a empty string in the chatroom, even if i just send "hey".
Am i missing some kind of formating or encodeing/decoding here?

Well you would think there would be some security that would be preventing you from posting like that so that might be the issue.
However I suspect that do.aspx is expecting JSON data not a NameValueCollection object.
If you take a look at this post it seems the recommended route is to use a Dictionary<string, string>() and then serialize it with the JavaScriptSerializer().serialize.

Related

Parse JSON from C# to AngularJS

I have an array of file names:
[HttpPost]
public JsonResult GetJSONFilesList()
{
string[] filesArray = Directory.GetFiles("/UploadedFiles/");
for (int i = 0; i < filesArray.Length; i++)
{
filesArray[i] = Path.GetFileName(filesArray[i]);
}
return Json(filesArray);
}
I need this in AngularJS as a list of objects so I can ng-repeat it out and apply filters. I'm unable to figure out how to get the JSON from the MVC controller to AngularJS.
I've tried the following to make it visible to the view for angular to grab, but I don't know how to make the ng-init see the function to return the list. It erros on "SerializeObject(GetJSONFilesList())" saying it doesn't exist in current context.
<div ng-controller="MyController" data-ng-init="init(#Newtonsoft.Json.JsonConvert.SerializeObject(GetJSONFilesList()),
#Newtonsoft.Json.JsonConvert.SerializeObject(Model.Done))" ng-cloak>
</div>
EDIT:
I've tried using http.get.
Test one:
alert('page load');
$scope.hello = 'hello';
$http.get('http://rest-service.guides.spring.io/greeting').
then(function (response) {
$scope.greeting = response.data;
alert($scope.greeting);
});
alert($scope.hello);
The alert in the http.get never fires, the other alerts do however.
Test two:
$http({
url: '/Home/testHello',
method: 'GET'
}).success(function (data, status, headers, config) {
$scope.hello = data;
alert('hi');
});
[HttpPost]
public string testHello()
{
return "hello world";
}
This causes the angular to break and nothing in the .js works.
Test three
alert('page load');
$scope.hello = 'hello';
$scope.GetJSONFilesList = function () {
$http.get('/Home/testHello')
.success(function (result) {
$scope.availableFiles = result;
alert('success');
})
.error(function (data) {
console.log(data);
alert('error');
});
alert('hi');
};
alert($scope.hello);
[HttpPost]
public string testHello()
{
return "hello world";
}
Alerts nothing from within it, other alerts work.
Fixed:
After some googling, I've found that using .success and .error are deprecated and that .then should be used. So by using .then this resulted in the C# being hit via debug.
Then after using console.log on the returned value found that to have anything be returned I needed to return the value from C# using "return Json(myValue, JsonRequestBehavior.AllowGet); "
And by viewing the object in the console in Chrome by using console.log, I could see my values were in the data part of the returned object.
It was stored in data as an array (as I was passing an array).
I could then get the data out of there by assigning the returned value.data to a scope and could call that in the view {{result[1]}} etc.
return Json(filesArray, JsonRequestBehavior.AllowGet);
$scope.fileList;
$http.get("/Home/GetFileList").then(function (result) {
console.log(result)
$scope.fileList = result.data;
})
Imagine that you divide your front end in three layers (MVC or MVVM) whatever you want.
When you need info from server, the best practice is to separate the logic that makes the request and the logic that manipulates the data.
More info about how to make the request you can find it reading about REST APIS in Consuming a RESTful Web Service with AngularJS.
Normally one of the layers requires the use of services and you can have your controllers and your services (the place where you get the raw data from the server and you make the request. For that you need to use the $http service from angularjs.
$http: The $http service is a core AngularJS service that facilitates communication with the remote HTTP servers via the browser's XMLHttpRequest object or via JSONP.
So basically it shows you how to make get, post and put requests. One example from the documentation is :
// Simple GET request example:
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Pay attention to the url because there is the place where you let your request knwow which method is going to be hit on the server to take the action. If your request is succesful, then you can use the parameter called response. From there, you can do whatever you want. If you decide to make that request part from your controller, you can assign it directly to a variable on your scope. Pay attention if you need to serialize the data. Something like
$scope.myResponseName = response.name ;
The first documentation link from above shows this example which does exactly what I tell you.
angular.module('demo', [])
.controller('Hello', function($scope, $http) {
$http.get('http://rest-service.guides.spring.io/greeting').
then(function(response) {
$scope.greeting = response.data;
});
});
After all the mentioned above, pay attention to what you want to display. Are you going to display the elements of an object array? The use on your HTML the ng-repeat directive. Are you going to display just a variable (No array nor object) then you use need to use an angular expression {{ }}
In summary:
By making an HTTP request, hit the correct method on server.
Make sure you are sending the JSON correctly and that the data is correct.
Retrieve the data on your response.
Assign the data to a variable on your scope and serialize the data if needed.
Display the data correctly depending if it is within an array, if it´s an object or if its just a variable.
I hope the explanation makes sense and check the documentation if you need more info.
You can build your viewmodel so that it contains the data you'd like to serialize and then pass it to angularJS in your view as follows:
<div ng-controller="MyController" data-ng-init="init(#JsonConvert.SerializeObject(myArrayData),
#Newtonsoft.Json.JsonConvert.SerializeObject(Model.Done))" ng-cloak>
and then in your angular controller have a function to receive the data as follows:
$scope.init = function (myArrayData) {
//do something with data
};
The above assumes you're trying to pass data from mvc to angularjs on page load. If you're trying to hit a controller and get data back to angularjs upon some event such as a button click, then you can write an angularjs function similar to the following (this will be an asynchronous request):
app.controller('MyController', function ($scope, $http, $window) {
$scope.ButtonClick = function () {
var post = $http({
method: "POST",
url: "/SomeController/SomeAjaxMethod",
dataType: 'json',
data: { path: $scope.Path},
headers: { "Content-Type": "application/json" }
});
post.success(function (data, status) {
//do something with your data
});
post.error(function (data, status) {
$window.alert(data.Message);
});
}
}
and your controller action would look something like:
[HttpPost]
public JsonResult SomeAjaxMethod(string path)
{
string[] filesArray = Directory.GetFiles(path);
for (int i = 0; i < filesArray.Length; i++)
{
filesArray[i] = Path.GetFileName(filesArray[i]);
}
return Json(filesArray);
}
other answers say to use .success in the angular function, .success and .error are deprecated, instead .then should be used.
Working result:
MVC:
public JsonResult GetFileList()
{
//form array here
return Json(myArray, JsonRequestBehavior.AllowGet);
}
The function needs to be of type JsonResult, and the returned value of Json using JsonRequestBehavior.AllowGet.
AngularJS:
$scope.fileList;
$http.get("/Home/GetFileList").then(function (result) {
console.log(result)
$scope.fileList = result.data;
})
This is in my AJS controller, using .then instead of .success. If you use console.log the result returned from the mvc controller and view it in the browser inspect you'll see the object with lots of other info and the values you want are in the .data section of the object.
So to access the values you need to do result.data. In my case this gives me and array. I assign this to a scope. Then in my view I can access the values by doing {{fileList[1]}} etc. This can also be used in ng-repeat e.g:
<div ng-repeat="file in fileList">
{{fileList[$index]}}
</div>
Each value in the array in the repeat can be accessed using $index which is the number of the repeat starting at 0.

Save a dynamic data set using AJAX in MVC

I have a razor view in which I generate the controls on the page generically by using a foreach loop on a list of data from a database. I am using DevExpress for my controls but I don't think that matters too much for solving this problem.
var docTypes = MyProject.GetDocumentTypes();
foreach(var docType in docTypes)
{
//Add controls (Example Control Below)
groupItem.Items.Add(i =>
{
i.Name = "checkDoc" + docType.Id;
i.NestedExtensionType = FormLayoutNestedExtensionItemType.CheckBox;
});
}
Usually when I write an AJAX call to save this data, I would write something like this. Note that this is being called when clicking a save button specifically:
function updateDocs() {
$.ajax({
url: '#Url.Action("SaveDocs", "Home")',
data: {
key: '#(Model.Id)',
docChecked: checkDoc1.GetValue(),
}, success: function(data){
},
error: function(data){
}
});
}
Then with the method:
public JsonResult SaveDocs(int key, bool docChecked)
{
//Save the data here
return Json(new { isSuccess = true },
JsonRequestBehavior.AllowGet
);
}
However, if I am generating the controls at runtime, I cannot know what exactly there is to pull for my parameters for the data section.
I was thinking that if I could somehow get this data into a Dictionary or something then I could pass it generically to a function with a parameter that accepts that Dictionary. If I can pass just some key data points to my Controller I can figure out how to save it from there. I would just need the value that the control holds and the control name itself passed in the simplest solution.
Thanks in advance for any assistance with this problem.
in your controller you can use this (this allows you to send any number of params of any type and parse them in the Action)
[HttpPost]
public JsonResult PostData(dynamic postData)
{
Dictionary<string,string> data = JsonConvert.DeserializeObject<Dictionary<string, string>>(((Newtonsoft.Json.Linq.JObject)postData)["data"].ToString());
...........
}
Or just send a dictionary
[HttpPost]
public JsonResult PostData(Dictionary<string,string> postData)
{
.......
}
The js call (for dynamic data type)
$http({
method: "POST",
url: Helper.ApiUrl() + '...',
data: { customer, applicant, accountNumber,... },
})

Kendo UI Scheduler Edit pop up window wont close after making changes

I am trying out the Kendo UI HTML Scheduler.
I was able to successfully read appointments from the database through my ASP.NET MVC appplication.
For Read : I am sending JsonResult from my ASP.NET controller.
For Update : The controller is getting a URL JSON encoded string which I deserialize and update the database and the return nothing to the caller.
When open an event to edit, make the changes and press "Save". The controller gets called and the record is updated but neither the pop-up window closes nor the scheduler gets updated.
The HTML Demo on Telerik website returns "callback()" on update and works fine but what am I missing on my code that would make the changes reflect.
**view**
<script>
$("#scheduler").kendoScheduler({
// configuration //
dataSource: {
batch: true,
transport: {
read: {
url : "http://localhost/Scheduler/Appointments",
dataType: "json"
},
update: {
Type:"POST",
url: "http://localhost/Scheduler/UpdateAppointment",
dataType: "json"
},
parameterMap: function(options, operation) {
if (operation !== "read" && options.models) {
return {models: JSON.stringify(options.models)};
}
}
},
schema: {
model: {
// my model
}
},
</script>
Controller
public JsonResult UpdateAppointment(String models)
{
if (models != null)
{
char[] charsToTrim = { '[', ']' };
string model_Trimmed = models.Trim(charsToTrim);
// Deserialize
Appointment SerializedAppointment = new JavaScriptSerializer().Deserialize<Appointment>(model_Trimmed);
Models.Entities.Appointment AppointmentToUpdate = db.Appointment.Where(x => x.TaskID == SerializedAppointment.TaskID).Single();
AppointmentToUpdate.Title = SerializedAppointment.Title;
AppointmentToUpdate.Start = SerializedAppointment.Start;
AppointmentToUpdate.End = SerializedAppointment.End;
db.SaveChanges();
}
return new JsonResult() {Data=null, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
Kendo needs to return a valid JSON format in your paramater map, so you could try this:
parameterMap: function(options, operation) {
if (operation !== "read" && options.models) {
return {models: JSON.stringify(options.models)};
}
return {};
}
Maybe this Link will also helps you...
(Copy just to prevent dead Links)
There is a breaking change with the new version of jQuery which affects the Kendo Q1 2013 version 2013.1.319
Since the empty result returned from the server in case everything is executed properly on the server side for the update and destroy requests, the error event of the dataSource is triggered because the empty result is not valid JSON.
The suggested resolutions when using the MVC Extensions are:
Use the Latest Internal Build version 2013.1.327
Change the response of the Update/Destroy actions from just serializing the ModelState to:
return Json(ModelState.IsValid ? new object(): ModelState.ToDataSourceResult());

How can I pass and access an array of objects on the server-side using AJAX in the C#.net Web-Pages with WebMatrix environment?

Firstly, I have already tried to find this answer on my own. I found a couple of pages on the topic:
http://forums.asp.net/t/1934999.aspx?Convert+any+json+string+to+an+array+or+object+in+c+ (This one uses a JSON string, and all, but it is an object and not an array of objects, so it doesn't seem to apply here).
Convert json to a C# array? (Here, it seems to have relevant answers, but none of them have helped me [probably because I am not handling this correctly on the server-side]).
Now, I have the following simple $.ajax request in jQuery:
$("#savePageBtn").click(function () {
$.ajax({
url: "/AJAX Pages/Compute_Save_Edit_Page.cshtml",
async: false,
type: "POST",
data: { "objectArr": jsonArr }, //more on exactly what jsonArr contains below...
success: function (response) {
console.log(response);
},
error: function (jqXHR, textStatus, error) {
alert("Oops! It appears there has been an AJAX error.\n\nPlease check the page you were attempting to edit.\n\n Error: " + textStatus + ".\n\nError Type: " + error + ".");
}
});
});
I have also tried: data: JSON.stringify(jsonArr), for the data line, but they both give me internal server errors of the code 500 when I try to access a property of a given object. Reading these errors, I can tell that the data is in "string" format (with JSON syntax, I'm sure) so I am not able to access the data as I would like. Even after I try to use C#'s Json.Decode method.
Here is the server-side code I have so far (Compute_Save_Edit_Page.cshtml):
#{
Layout = "";
if (IsAjax)
{
var reader = new StreamReader(Request.InputStream);
var json = reader.ReadToEnd();
var objectArr = Json.Decode(json);
for (var i = 0; i < objectArr.Length; i++)
{
<!-- -->#:#objectArr[i].objectName;
<!-- --><br/>
}
}
else
{
Context.RedirectLocal("~/");
}
}
I think I know what I need, but I can't seem to get anything to convert the JSON string back into an array of objects, like I want.
In jQuery I have been accessing this exactly like you would expect. To get the object name of an object at the first index, for instance, I would type: jsonArr[0].objectName
I would like to be able to get this accessible in much the same way once I have it on the server-side, but nothing I try works.
Additional Info:
It's appropriate to mention that the array of objects contains objects that don't all have the same properties (which is why trying the top answer in the second link I provided won't work, if I'm even understanding it correctly).
Here is a sample of a few objects in the array of objects (in no real particular syntax):
Object {
caption: "",
fileName: "Okmulgee_Library.jpg",
objectID: "176",
objectName: "Image",
pageOrder: "1",
size: "medium"
}
Object {
alignment: "center",
bold: false,
italic: false,
objectID: "177",
objectName: "Paragraph",
pageOrder: "2",
underline: false,
value: "For more information about the Okmulgee Public Library, call (918)-756-1448."
}
Object {
bold: false,
italic: false,
objectID: "179",
objectName: "Text",
pageOrder: "3",
underline: false,
value: "Or visit their website at"
}
UPDATE FROM CHROME'S Network > Headers
Request URL:http://localhost:10226/AJAX%20Pages/Compute_Save_Edit_Page.cshtml
Request Method:POST
Status Code:500 Internal Server Error
Request Headersview source
Accept:application/json, text/javascript, */*; q=0.01
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:0
Cookie:.ASPXAUTH=AEBDE22DCB622D796F8897945434328CECAEB25BF5D24CBA9CB1C32A58D82BC5CF68F33EF2CA7012DECFE87F91C39E7471DE7C2903CE476DF8781E0B0CE862C8AF10A23CD1B52BDFBA9042290426BBD024663A2D95C02A54EBA9E98D3DE25A44415395F5CDAA1E65A0EDDC3D9598F2A7660E3376159D82986E3E4EFEB05F150D02DC788D8F0FC0D62FF8B80708D05A276789A3D54DC79F598D57D19990426F68
Host:localhost:10226
Origin:http://localhost:10226
Referer:http://localhost:10226/CMS%20Interface/EditPages/E-UtilityBilling.cshtml
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36
X-Requested-With:XMLHttpRequest
Response Headersview source
Cache-Control:private
Content-Length:5732
Content-Type:text/html; charset=utf-8
Date:Fri, 25 Oct 2013 19:00:34 GMT
Server:Microsoft-IIS/7.5
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?QzpcVXNlcnNcY3JhZGViYXVnaFxEb2N1bWVudHNcTXkgV2ViIFNpdGVzXE9rbXVsZ2VlIE9ubGluZSA0LjBcQUpBWCBQYWdlc1xDb21wdXRlX1NhdmVfRWRpdF9QYWdlLmNzaHRtbA==?=
I think you'll find your data in the Request.InputStream. Try the following:
var reader = new StreamReader(Request.InputStream);
var json = reader.ReadToEnd();
var objArray= Json.Decode(json);
You will need to convert your Javascript object to JSON first by using JSON.stringify on it:
data: JSON.stringify(jsonArr),
Okay, I think I've finally got it.
I decided to try something I had tried previous to posting this question: JSON.stringify in the AJAX call (apparently jQuery doesn't automatically format the data based on contentType nor simply detecting the kind of data that it is).
The problem before was that I had NO idea that I would be able to find my data on the server-side with Request.InputStream. In fact, I am still not clear as to why or when data could be found in this manner or even what determines that it should be stored there as opposed to something that could be called by, say, Request.Form["objectArr"], etc.
So, when I tried to use JSON.stringify this time, I combined that with what Mike had posted in his answer for how to retrieve this server-side (i.e., using the Request.InputStream method).
Once I used both (as well as, removing the identifier in the data: portion of the ajax call), I started to see and even return relevant data.
In short, here is what I have now that works...
The jQuery AJAX code:
$.ajax({
url: "/AJAX Pages/Compute_Save_Edit_Page.cshtml",
async: false,
type: "POST",
data: JSON.stringify(jsonArr),
success: function (response) {
console.log(response);
},
error: function (jqXHR, textStatus, error) {
alert("Oops! It appears there has been an AJAX error.\n\nPlease check the page you were attempting to edit.\n\nError Type: " + error + ".");
}
});
And here is the server-side (C#) code that simply returns two properties of each object in the array:
#{
Layout = "";
if (IsAjax)
{
var reader = new StreamReader(Request.InputStream);
var json = reader.ReadToEnd();
var objectArr = Json.Decode(json);
for (var i = 0; i < objectArr.Length; i++)
{
#:#objectArr[i].objectName - #objectArr[i].objectID
}
}
else
{
Context.RedirectLocal("~/");
}
}
So, if I understand it correctly (and PLEASE correct me if I'm wrong), you CAN'T just send an array of objects to the server with AJAX. In fact, I wouldn't be surprised if you couldn't even send a array, at all. But you CAN send a simple variable like string or int. So, using JSON.stringify, I am using a function that translates the array of objects into one large JSON string, reading the input stream on the other side with C#, and then using another C# method to parse the JSON string back into an array of objects, which was how I wanted the data.
Thanks to all who helped me through this one, and for what it's worth, I really feel like I even learned something about the very purpose of JSON in the web environment today.

Trying to return json and populate selectlist

Im trying to return a Json result from my controller and populate a selectlist using jQuery.
But the code dont even hit the Json method in my controller.
My selectlist
<select id="MyList"></select>
My javascript
<script type="text/javascript">
$(document).ready(function () {
$.getJSON("#Url.Action("GetProductJson", "Product")", null, function (data) {
$("#MyList").addItems(data);
});
});
$.fn.addItems = function (data) {
return this.each(function () {
var list = this;
$.each(data, function (index, itemData) {
var option = new Option(itemData.Text, itemData.Value);
list.add(option);
});
});
};
</script>
My Json method in ProductController
[HttpGet]
public JsonResult GetProductJson()
{
var list = new List<SelectListItem>
{
new SelectListItem { Value = "1", Text = "Aron" },
new SelectListItem { Value = "2", Text = "Bob" },
new SelectListItem { Value = "3", Text = "Charlie" },
new SelectListItem { Value = "4", Text = "David" }
};
return Json(list);
}
You should enable JSON for GET requests which is disabled by default. This happens by passing a second argument to the Json method:
return Json(list, JsonRequestBehavior.AllowGet);
Now go ahead and install FireBug. If you had done that prior to posting this question on StackOverflow you could have inspected the AJAX request in your browser and could have seen that the server returns 500 status code and when you inspected the response you would have seen the exact error message and not only that - you would also have seen a suggestion on how to fix it. The suggestion is basically what I posted here in my answer. Thus you wouldn't even had the need to post your question as you would be able to solve it by yourself. I cannot possibly imagine people doing web development without a tool such as FireBug or Chrome Developer Tools. It's like trying to build a house with your own bare hands and without any tools.
you need to add JsonRequestBehavior.AllowGet in your json method
from Phil haack post JsonHijacking
By default, the ASP.NET MVC framework does not allow you to respond to
an HTTP GET request with a JSON payload. If you need to send JSON in
response to a GET, you'll need to explicitly allow the behavior by
using JsonRequestBehavior.AllowGet as the second parameter to the Json
method. However, there is a chance a malicious user can gain access to
the JSON payload through a process known as JSON Hijacking. You do not
want to return sensitive information using JSON in a GET request.

Categories