I am trying to bind a JSON stringified object to a model and few other strings in the controller and it is not working.
is it not possible,
$.ajax({
url: "/SrcManager/AddDataSource",
type: "POST",
data: JSON.stringify({
content: ct,
dataSourceName: $("#dataSrcName").val(),
parameters: parametersCollection,
sourceContentId: sourceContentId,
sourceId: null,
type: contType
}),
success: function (data) {
if (data.length > 1)
{
alert("DataSource Saved Successfully");
$("#dataSrcId").val(data);
}
}
});
and var parametersCollection = [];
function IPParameters(paramName, paramValue) {
this.ParamName = paramName;
this.ParamValue = paramValue; }
*** action method : public string AddDataSource(ContentModel scvm){.........}
Why does the above not work. Is this not supported or any mistake in the code, kindly suggest the right way.
In the ContentModel, i map the parameters to List<Parameters>.
I have added the JsonValueProviderFactory also in global.asax.
The C# model is :
public class SourceContentViewModel
{
public string sourceId { get; set; }
public string dataSourceName { get; set; }
public string sourceContentId { get; set; }
public string content { get; set; }
public string type { get; set; }
public List<Parameters> parameters { get; set; }
public SourceContentViewModel()
{
parameters = new List<Parameters>();
}
}
public class Parameters
{
public string ParamName { get; set; }
public string ParamValue { get; set; }
}
You can't send JSON to an ASP.NET MVC 2 application as there is no JSON provider factory out-of-the-box that will allow you to read the request. It is built in ASP.NET MVC 3. You may take a look at the following blog post and include the JsonValueProviderFactory discussed there. Then you will be able to send JSON requests to your ASP.NET MVC 2 controller actions after registering it:
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
}
Also notice the contentType: 'application/json; charset=utf-8' setting when sending the request which instructs the binder that you are sending a JSON request.
Related
I have a strange problem. I have a C# data structure with two classes:
public class AddQuestionModel2
{
public int? QuestionID { get; set; }
public string QuestionString { get; set; }
public int? TrueAnswer { get; set; }
public QuestionType Type { get; set; }
public IEnumerable<AddQuestionModelAnswer> Answers { get; set; }
}
public class AddQuestionModelAnswer
{
public int? ID { get; set; }
public string AnswerString { get; set; }
public bool? IsRight { get; set; }
public int? Order { get; set; }
}
public enum QuestionType
{
SingleSelect,
MultiSelect,
OrderAnswers,
FillingGap,
ExampleRequired,
TrueOrFalse
}
The javascript generates the javascript object (which looks fine for the data structure) and JSON.stringify translates to the following json string:
{"QuestionString":"<p>Question 1</p>","TrueAnswer":"0","Type":"0","Answers":[{"AnswerString":"<p>Answer 1</p>","IsRight":"0"},{"AnswerString":"<p>Answer 2</p>","IsRight":"0"},{"AnswerString":"<p>Answer 3</p>","IsRight":"0"},{"AnswerString":"<p>Answer 4</p>","IsRight":"0"}]}
The json data is sent by the following jquery command:
$.ajax({
url: "/Questions/Add",
method: "POST",
async: true,
dataType: "json",
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
success: function (e) {
if (e.Success) {
document.location = "/Questions";
}
},
error: function (e) {
var i;
for (i in e) {
console.log(e[i]);
}
}
});
On the C# side, I have the following method to receive the post data:
[HttpPost]
public async Task<string> Add([FromBody] AddQuestionModel2 q)
{
var ctx = this.HttpContext;
JsonResultModel res = new JsonResultModel();
}
The parameter "q" is always null. If I expand ctx (HttpContext), the Request.Form data is threw System.InvalidOperationException.
Does any if you have any idea what could be wrong?
The biggest problem is that I am unable to debug what is happening within HttpContext and why it is throwing exception.
Thanks in advance!
Gabor
In you ajax code try data:data, instead of data: JSON.stringify(data). The JSON.stringify() method converts a JavaScript object or value to a JSON string, but ajax data need JavaScript object. Another things to try instead of 0 or 1 use "true" or "false" in your bool fields.
In the postman everything works.
I am having all kinds of errors migrating from ASP.NET Core 2.2, to 3.1.
My latest error is that the object I am receiving via a Http Post is null.
Here is the code that receives the object, and in this case the model is null.
[HttpPost]
public async Task<IActionResult> MyAction([FromBody] BoardMoveModel model)
The model class:
public class BoardMoveModel
{
public int BoardId { get; set; }
public int TicketId { get; set; }
public int DestinationStatusId { get; set; }
public int SourceStatusId { get; set; }
public IEnumerable<int> SourceStatusList {get; set;}
public IEnumerable<int> DestinationStatusList {get; set;}
}
And the Javascript code:
var data = {
TicketId: el.id,
DestinationStatusId: targetStatusId,
SourceStatusId: sourceStatusId,
SourceStatusList: sourceList,
DestinationStatusList: destList
};
$.ajax({
async: true,
url: "/Area/Board/MyAction",
type: "POST",
contentType: "application/json; charset=utf-8",
headers: {
RequestVerificationToken:
$('input:hidden[name="__RequestVerificationToken"]').val()
},
data: JSON.stringify(data)
}).done(function(result) {
Here is the actual JSON Payload:
{
"TicketId":"150",
"DestinationStatusId":"5",
"SourceStatusId":"6",
"SourceStatusList":[],
"DestinationStatusList":["140","150"]
}
Model is null because it's invalid for binding. In JSON you are passing in string values while model requires integers. Change either to match and it should work. Binding is by default case sensitive, but it shouldn't be a problem with code you've provided.
Try sending this as application/json body
{
"TicketId":150,
"DestinationStatusId":5,
"SourceStatusId":6,
"SourceStatusList":[],
"DestinationStatusList":[140,150]
}
I would like to collect some data using AngularJS and post it back to my ASP.NET WebAPI controller.
I have defined my business object like this (which just aims to record overall annual petrol consumption along with consumption every month):
public class PetrolViewModel
{
public double petrol_annual { get; set; }
public int petrol_measure { get; set; }
public List<Month> months { get; set; }
}
public class Month
{
public double jan { get; set; }
public double feb { get; set; }
}
In my Angular code I have:
var app = angular.module('petrol', []);
app.controller('PetrolController', function ($scope, $http) {
$scope.petrol = {};
$scope.petrol.months = {};
$scope.sendForm = function() {
$http({
method: 'Post',
url: 'api/values',
data: $scope.petrol
}).success(function (data, status, headers, config) {
console.log(data);
console.log(status);
console.log(headers);
}).error(function (data, status, headers, config) {
console.log(data);
console.log(status);
console.log(headers);
});
};
});
When I submit the form data and leave the WebApi controller to receive an anonymous object it seems to work and I get my form data:
But, if I change this and try to pass in the ViewModel I defined earlier I get a null object being passed in:
I want to take full advantage of the ASP.NET features to automatically map the matching names and deliver me a populated Object that I can then handle in my code. I don't want to have to map the anonymous object to the ViewModel.
So, the programming question is: How do I make sure my AngularJS object can be matched to a ViewModel?
In tutorials I've been watching this seems to "just work" for everyone else so they tend not to cover it in much detail.
Here is the JSON that is being sent up, according to Fiddler:
{"months":{"jan":"10","feb":"10","mar":"10","apr":"10","may":"10","jun":"10","jul":"10","aug":"10","sep":"5","oct":"5","nov":"20","dec":"10"},"petrol_annual":"120","petrol_measure":"1"}
I'm not sure why petrol_annual or petrol_measure aren't model binding correctly, but the List<Month> needs to be Month instead:
public class PetrolViewModel
{
public double petrol_annual { get; set; }
public int petrol_measure { get; set; }
public Month months { get; set; }
}
This is because months in the JSON is an object, not an array. It should match up with the Month class on the server. The Month class should also include entries for all months, but you may have just ommitted those for brevity in your OP.
Below works. Perfectly fine.
Code:
public class CatergoriesViewModel
{
public string OrderSelected { get; set; }
public string CatergoryName { get; set; }
}
var data = { catergoryName: "TestCat", orderSelected: "true" };
$http.post("Category", data)
.then(function (response) {
$scope.test = response.data;
}, function (error) {
$scope.test = error;
});
I have created a page with a KnockoutJS viewmodel. I want to post the Data to my Server using Web API.
I use this AJAX post:
$.ajax({
url: "/api/blogpost",
contenttype: "application/x-www-form-urlencoded",
data: '=' + encodeURIComponent(ko.toJSON(self.Blog)),
type: "POST",
dataType: "JSON",
timeout: 10000,
success: function (Result) {
},
error: function (xhr, status) {
alert(status + " - " + xhr.responseText);
}
});
To send the JSON data to my Web API method.
This is the JSON that is sent to the server:
{
"BlogTitle": "Sample Post",
"BlogHTML": "<p><strong>Sample JSON Blog Post</strong></p>\n\n<h1><strong>It never works :( </strong></h1>\n",
"BlogThumbnail": "http://mysystemURL/SamplePost/What.jpg",
"BlogSummary": "This is a sample post",
"BlogFQURL": "Sample_Post",
"BlogTags": [
"json",
"devlopment",
"newtag",
""
],
"BlogCategory": 1
}
My WEB API method received the JSON data correctly. The RAW string value looks like this:
"{\"BlogTitle\":\"Sample Post\",\"BlogHTML\":\"<p><strong>Sample JSON Blog Post</strong></p>\\n\\n<h1><strong>It never Works :(</strong></h1>\\n\",\"BlogThumbnail\":\"http://mysystemURL/SamplePost/What.jpg\",\"BlogSummary\":\"This is a sample post\",\"BlogFQURL\":\"Sample_Post\",\"BlogTags\":\"[\\\"json\\\",\\\"devlopment\\\",\\\"newtag\\\",\\\"\\\"]\",\"BlogCategory\":1}"
when I use the JSON visulizer on my data I get this:
I use this BlogPost vari = JsonConvert.DeserializeObject<BlogPost>(value); to deserialize my object but everything stays null
My BlogPost Object looks like this:
public class BlogPost
{
public int BlogPostID { get; set; }
public string BlogPostTitle { get; set; }
public string BlogPostHTML { get; set; }
public string BlogPostThumbnailURL { get; set; }
public string BlogPostSummary { get; set; }
public string BlogPostFQURL { get; set; }
public int BlogPostCategory { get; set; }
public List<TagDTO> BlogPostTags { get; set; }
}
I am really stumped.. Any help would be greatly appreciated!
Your property names don't match. The C# object's properties are BlogPost* and the JSON has Blog*, without the Post.
Correct the names either on the Javascript or on the C# side or use the JsonProperty attribute to specify the name of the serialized property.
I am trying to get model binding with MVC3 and JSON working but I have had no luck... No matter what I do I seem to be getting a null model on the server.
Method Signature:
public ActionResult FilterReports(DealSummaryComparisonViewModel model)
Javascript UPDATED:
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$('#filter-reports').click(filterReports);
});
function filterReports() {
var filters = {
SelectedRtoId: $('#SelectedRtoId').val(),
SelectedPricingPointId: $('#SelectedPricingPointId').val(),
SelectedLoadTypeId: $('#SelectedLoadTypeId').val(),
SelectedBlockId: $('#SelectedBlockId').val(),
SelectedRevisionStatusId: $('#SelectedRevisionStatusId').val()
}
var dealSummaries = { SelectedItemIds: $('#SelectedItemIds').val() }
var model = { ReportingFilters: filters, DealSummaries: dealSummaries }
$('#selected-items select option').attr("selected", "selected");
$.ajax({
url: '#Url.Action("FilterReports")',
data: model,
contentType: 'application/json',
dataType: 'json',
success: function (data) {
alert(data);
}
});
}
</script>
Models:
public class DealSummaryComparisonViewModel
{
public ReportingFiltersViewModel ReportingFilters { get; set; }
public LadderListViewModel DealSummaries { get; set; }
}
public class LadderListViewModel
{
public MultiSelectList AvailableItems { get; set; }
public int[] SelectedItemIds { get; set; }
public MultiSelectList SelectedItems { get; set; }
}
public class ReportingFiltersViewModel
{
public int? SelectedRtoId { get; set; }
public ICollection<Rto> Rtos { get; set; }
public int? SelectedPricingPointId { get; set; }
public ICollection<PricingPoint> PricingPoints { get; set; }
public int? SelectedLoadTypeId { get; set; }
public ICollection<LoadType> LoadTypes { get; set; }
public int? SelectedBlockId { get; set; }
public ICollection<Block> Blocks { get; set; }
public int? SelectedRevisionStatusId { get; set; }
public ICollection<RevisionStatus> RevisionStatuses { get; set; }
public bool? DealStatus { get; set; }
}
The model looks fine on the client side:
{"ReportingFilters":{
"SelectedRtoId":"5",
"SelectedPricingPointId":"20",
"SelectedLoadTypeId":"55",
"SelectedBlockId":"21",
"SelectedRevisionStatusId":"11"
},"DealSummaries":{
"SelectedItemIds":["21","22","23","24","25"]
}}
So why am I getting nothing back on the controller? This has been giving me trouble for the past two days so please help! Thanks!!
UPDATE
I've updated my javascript section to what I am currently using. This section now returns the model to the controller with the ReportingFilers and DealSummaries objects, but all values within are null.
Does it possibly have something to do with the values being strings? If so, how can I fix this?
Change your $.getJSON line to:
$.ajax({
url: '#Url.Action("FilterReports")',
data: JSON.stringify(viewModel),
contentType: 'application/json',
dataType: 'json',
success: function (data) { alert(data); }
});
This way MVC knows that it is receiving JSON and will bind it to your model correctly.
Here's a few different things you could try:
Apparently you shouldn't use nullable properties in your objects if you want to use the DefaultModelBinder: ASP.NET MVC3 JSON Model-binding with nested class. So you could try making your ints not nullable or if that's not an option, implement IModelBinder yourself?
Have you marked your classes with the SerializableAttribute?
Try setting the type parameter in the ajax method to 'POST' - it will be using 'GET' by default.. type: 'POST'
Try explicitly setting the contentType parameter in the ajax method to this instead... contentType: 'application/json; charset=utf-8'
And finally, are you definitely using MVC 3, not MVC 2? I ask because MVC 3 has the JsonValueProviderFactory baked into the framework where as MVC 2 didn't so if you were using MVC 2 that might explain the problem you're having...
Ok, replace:
{ model: JSON.stringify(viewModel) }
with
{ model: viewModel }
You're mixing objects with JSON strings, so jQuery will JSON.stringify the entire object. Which will double encode viewModel.
here is what I would suggest, in your controllers action method should look as follows:
public JsonResult FilterAction(string model)
{
var viewModel=new JavaScriptSerializer().Deserialize<DealSummaryComparisonViewModel>(model);
}
Also make sure your request is reaching the right action and look at Firebug for the same.
Try this:
var filters = new Object();
filters.SelectedRtoId = $('#SelectedRtoId').val();
filters.SelectedPricingPointId = $('#SelectedPricingPointId').val();
filters.SelectedLoadTypeId = $('#SelectedLoadTypeId').val();
filters.SelectedBlockId = $('#SelectedBlockId').val();
filters.SelectedRevisionStatusId = $('#SelectedRevisionStatusId').val();
var dealSummaries = new Object();
dealSummarties.SelectedItemIds = $('#SelectedItemIds').val();
var viewModel = new Object();
viewModel.ReportingFilters = filters;
viewModel.DealSummaries = dealSummaries;
$('#selected-items select option').attr("selected", "selected");
$.getJSON('#Url.Action("FilterReports")', { model: JSON.stringify(viewModel) }, function (data) {
alert(data);
});