I am having trouble serializing my model using #Html.Raw in javascript. I basically want to serialise the model so I can pass it through a callback method on the client and then de-serialise it on the server.
[Serializable]
public class AdvanceSearch
{
public string Name{ get; set; }
public DateTime? Date { get; set; }
}
And in the javascript
var now = #Html.Raw(Json.Encode(Model));
alert(now.Name);
But the alert always comes back as null which therefore means it hasn't serialised. Am I missing anything?
Cheers
By using the Newtonsoft json serializer/deserializer this can be achieved. To serialize your model use as below.
Name space: Newtonsoft.Json;
var now = JsonConvert.SerializeObject( Model );
To deserialize,
ViewModel vm = JsonConvert.DeserializeObject<ViewModel>( obj );
Here ViewModel is your view model. Hope it helps!
Related
I've been trying for the past hour and can't get it. At this point my controller looks like
public ActionResult GenerateMasterLink (string assetsJSON)
{
...
}
and I've confirmed that it is being passed a string like
[["Microsoft","Azure","roman_column.png"],["Microsoft","Azure","runphp.cmd"],["Microsoft","Azure","runphp.cmd"],["Microsoft","Azure","Picture1.png"],["Microsoft","Azure","vertical-align-scrnsht.png"],["Microsoft","Azure","vertical-align-scrnsht.png"]]
The only question I have is how I get the damned stuff out of it!
I've tried creating a class
public class ThreePartKey
{
public string organizationName { get; set; }
public string categoryName { get; set; }
public string fileName { get; set; }
}
and then done
ThreePartKey [] assetList = new JavaScriptSerializer().Deserialize<ThreePartKey []>(assetsJSON);
which gives me
Failed to load resource: the server responded with a status of 500
(Internal Server Error)
in my browser's console some of the time, and other times gives me
Additional information: Type
'AllyPortal.Controllers.SurfaceAssetsController+ThreePartKey' is not
supported for deserialization of an array.
as a Visual Studio error.
I've experimented with a million things and can't get this right. All I want is to have the JSON in some C# data structure where I can actually use it in my controller. Any suggestions?
You are trying to deserialize to incompatible model. You string input can be deserialized into string[][] variable but in order to allow deserializations into an ThreePartKey you need to name those values per property:
[[organizationName: "Microsoft",...]]
This will copy right value to your model
The problem is that your target datatype doesn't match the source datatype.
If you are converting an array of array of strings, you must deserialize into another array of array of strings, only them, you'll be able to convert it into whatever you want:
In short, replace
ThreePartKey [] assetList = new JavaScriptSerializer().Deserialize<ThreePartKey []>(assetsJSON);
for
ThreePartKey[] assetList = new JavaScriptSerializer().Deserialize<string[][]>(assetsJSON)
.Select(el => new ThreePartKey() {organizationName = el[0], categoryName = el[1], fileName = el[2]})
.ToArray();
I have a quick question. I've created a custom drop-down HTML control that dynamically grabs "nodes" from a database. I turned this into an Umbraco (v7) datatype that can be used as an Umbraco property in the admin section.
Unfortunately, when the user picks one of the items and saves, it does not properly store this info. I've determined that this is because when Umbraco tries to save to the DB, it's NodeId is empty. I need to populate this before we save the data. Unfortunately, I haven't found any easy way to do this.
Can anyone point me in the right direction? Populating the NodeId before I push the model to the CS Controller (which should update the SQL DB) should work... or is it possible to make an angularJS that pushes TWO parameters and let the C# handle this?
Anyone have any ideas?
Here's the HTML Editor:
<select ng-controller="Dmns.DDLAllNodesController" data-ng-model="selectedOption">
<option ng-repeat="gNode in galaxyNodes.data" value="{{gNode}}">
{{gNode.KioskNodeId}} -- {{gNode.MachineName}}
</option>
</select>
And here's the AngularJS, where I'd like to add the Umbraco's Node Id to the model before submitting to the C#
$scope.$on("formSubmitting", function () {
$scope.selectedOption({
Id: $routeParams.Id // This does not update properly
});
$scope.$apply();
getAllNodesResource.save($scope.selectedOption); // Sends old data
});
And here's the model I'm returning, in case this helps:
[Serializable]
[DataContract]
public class KioskNode
{
[DataMember]
public int Id { get; set; }
[DataMember]
public int NodeId { get; set; }
[DataMember]
public int KioskNodeId { get; set; }
[DataMember]
public string MachineName { get; set; }
}
So I found the reason why it wasn't populating correctly. I wasn't deserialing the object from JSON, which means I couldn't get the child properties.
This fixed my problem:
var deJson = angular.fromJson(node);
return $http.post("/umbraco/backoffice/api/DDLNodes/PostSave", {
Id: 0,
NodeId: id,
KioskNodeId: deJson.KioskNodeId,
MachineName: deJson.MachineName
});
This let me pass the variables (updated) I need back to Backoffice to save it to the DB.
I have the following class on my server:
public class JsonDialog
{
public IEnumerable<string> Errors { set; get; }
public string Modified { set; get; }
public string ModifiedBy { get; set; }
public string PartitionKey { set; get; }
public string PartitionKeyNew { set; get; }
public string RowKey { get; set; }
public string RowKeyNew { get; set; }
public bool Success { set; get; }
}
In my MVC action method I return a JsonResult:
return Json(new JsonDialog
{
Success = false,
Errors = errors
});
In my client code I have the following:
$.ajax({
url: href,
dataType: 'json',
type: 'POST',
data: $form.serializeArray()
})
.done(onDone)
.fail(onFail);
var onDone = function (json, textStatus, XMLHttpRequest) {
json = json || {};
if (json.Success) {
Because I am using a class on the server the compiler checks to ensure I don't make any spelling mistakes and for example it will not allow me to enter "success = false". However on the client there's no checking and I could code json.sUccEss and it would still be okay with that but it would not give me the desired result.
Is there any way in Javascript that I can have some error checking like I have on the server? Anything like getting data into a class and having the IDE check that class fields are correct?
I solve this (partially) by creating a matching object in JS with, what I refer to as a 'factory' method (but that's a misnomer if you're using the term 'factory' as is referred to here. It's really more analogous to 'casting', but since JS doesn't have strong typing, that's not exactly right either.
Obviously, this code pattern is also pretty verbose if all you're doing is trying to get intellisense working, but if you have methods on your JS-side object... we'll fictionally say: JsonResult.prototype.markErrorsReviewed...then this pattern where you get an instance of a given 'class' is helpful.
For the sake of brevity, I'm going to just use your C# class on which to base my JS:
var JsonResult = function () {
this.Errors = [];
this.Modified = null;
this.ModifiedBy = null;
//...rest of your properties, defaulted as necessary
}
JsonResult.factory = function (o) {
var j = new JsonResult();
$.extend(j, o);
//do other processing here if needed (for example, ASP.NET serializes DateTime retardedly)
return j;
}
AJAX:
$.ajax({
success: function(json, status, xhr) {
var myobj = JsonResult.factory(json);
//VS2010 will now give you intellisense w/ proper property names on myobj
//Note: it's still buggy and sometimes won't detect things properly, but it usually works
}
});
May be there could be tools but if you can achieve that following ways:
In the controller you render the partially view instead of json result and pass the class object on that then on that view you have to write the objcetName.PropertyName and it would you check it.
Maybe there are good Text Editors that would help you, but there is no such thing for Javascript.
Editors like TextSublime can fake the code introspection and give an in file search to give help typing the same names.
IDE like Eclipse or Netbeans do a better job but are still really far away from what you want.
Javascript is not a language strongly typed like Java or C# (if we can say that they are...) so you won't find all those candy features you have with VS and C#.
This is what NetBeans does and this is not as advanced as you wish.
I am using ASP.NET 4, MVC3, EF 4.3 (Code first) and knockout JS. I am currently working on the create and edit forms for one of my more complicated models. This has various fields attached to it, as well as several collections for related objects (many-to-many). I'll pose my question for the edit scenario, as this is the harder of the two.
I would like the user to be able to edit all of the fields of the model, which I have put in a viewmodel. For displaying and adding additional Skills (one of the many-to-many collections) I have decided to use knockoutjs to great effect, which displays the serialized initial objects of the collection nicely as well as allowing me to add more.
My problem is how to save this rather complicated model by sending it back to the controller. As many of my fields can be represented in the view by standard HTML helpers nicely, I would like to avoid multiple AJAX posts or binding every single field to a ko.observable(array). What I really want is to take only the many-to-many collections, bind them to ko.observablearrays, and somehow send them back as part of the standard strongly typed mvc view form post.
Is this even possible? And if so, how would I approach it? I'd really appreciate any help, my research so far has produced no useful results. Am willing to post code snippits if that helps to better describe the problem.
edit: sample viewmodel for edit form as requested
namespace MyProject.Models
{
[NotMapped]
public class JobViewModel
{
public int JobID { get; set; }
[Required]
public string Title { get; set; }
[Required]
public string Description { get; set; }
[Display(Name = "Start Date")]
[DataType(DataType.Date)]
public DateTime StartDate { get; set; }
[Display(Name = "End Date")]
[DataType(DataType.Date)]
public DateTime EndDate { get; set; }
// Foreign Keys
[Display(Name = "Hiring Manager")]
[Required]
public string HiringManagerID { get; set; }
[Display(Name = "Assigned User")]
public string AssignedUserID { get; set; }
//Collections for many-to-many properties
public List<JobSkillViewModel> JobSkills { get; set; }
}
}
and my ViewModel held in the collection:
namespace MyProjectModels
{
[NotMapped]
public class JobSkillViewModel
{
public int SkillID { get; set; }
public int LevelID { get; set; }
public string SkillName { get; set; }
public string LevelDescription { get; set; }
}
}
I wouldn't recommend doing it this way but if you feel you must post with the form. Why not simply serialize the collection as JSON into a hidden form field.
<input name="something" type="hidden" data-bind="text: collectionToJson" />
Your collectionToJson method would call ko.toJSON or the mapping equivalent and then you would have to handle deserialization yourself server side.
I don't think you are doing to find a nice clean way to post back via a form AND model bind. If I were you I would bind the whole form to a json model and post back a complete well formed json object for automatic model binding. The resultant code on the server-side would be much cleaner IMHO.
Hope this helps.
I am using MVC.
I have a view model which contains a Business object.
I need to post this Business Object back to a controller action using AJAX.
For now, I am using Url.Action function to create my request Url for AJAX and pass the Business Object id as a request parameter to the action. I then have to retrieve the object from the database to use it.
Is there a way (using Json) to pass this object as an Object? The object is shown below
public class BusinessObject : BaseBusinessObject
{
public virtual string Id { get; set; }
public virtual IDictionary Data { get; set; }
public virtual IDictionary Collections { get; set; }
}
The controller action should ideally have a deifinition like ...
public ActionResult DOThis(BusinessObject bo) {}
What you are looking for is FORM Binding, there are lot of resources available, This link gives you some insight.
You should use the JsonResult for going from the server to the client. http://www.ajaxprojects.com/ajax/tutorialdetails.php?itemid=399#start
The DefaultModelBinder will take care of the binding to the server. There is also a section in this page talking about calling from JQuery to the server and getting back the JsonResult.
Hope this helps!