Sending model data from Knockout back to MVC 3 - asp.net-mvc-3

I am new to knockout and am having a hard time trying to get my data from Knockout back to my server. I keep getting an error of 'No parameterless constructor defined for this object.' Any help would be appreciated.
My Knockout model is as follows
function partSummary(item) {
var self = this;
self.ID = ko.observable(item.ID);
self.serialNumber = ko.observable(item.SerialNumber);
self.description = ko.observable(item.Description);
self.manufacturer = ko.observable(item.Manufacturer);
self.creationDate = ko.observable(item.DateCreated);
self.active = ko.observable(item.IsActive);
}
My code to send the data back the server is
self.savePart = function() {
$.ajax("/PartKO/UpdatePart", {
data: ko.toJSON(self.partDetails),
type: "post",
contentType: 'application/json',
dataType: 'json'
});
};
My MVC controller is
[HttpPost]
public JsonResult UpdatePart(PartDetail part)
{
var dbPart = new PartGenericAccessor();
dbPart.ID = part.ID;
dbPart.Load();
dbPart.Description = part.Description;
dbPart.IsActive = Convert.ToBoolean(part.IsActive);
var manufacturers = ManufacturerAccessor.LoadAll<ManufacturerAccessor>();
if (part.Manufacturer != null)
{
var manufacturer = (from p in manufacturers where p.Name == part.Manufacturer select p.ID).First();
dbPart.ManufacturerID = manufacturer;
}
dbPart.Save();
return Json("Success!!");
}
And my server side model is
public class PartDetail
{
public PartDetail(Guid id, string serial, string description, string manufacturer, DateTime created, bool isActive)
{
ID = id;
SerialNumber = serial;
Description = description;
Manufacturer = manufacturer;
DateCreated = created.ToShortDateString();
IsActive = isActive.ToString(CultureInfo.InvariantCulture);
}
public Guid ID { get; set; }
public string SerialNumber { get; set; }
public string Description { get; set; }
public string Manufacturer { get; set; }
public string DateCreated { get; set; }
public string IsActive { get; set; }
}

You need to supply a parameterless constructor for your MVC model:
public class PartDetail
{
public PartDetail()
{ ... }
}
When the data comes back from the server, MVC will create an empty object, using the parameterless constructor and then call the 'set' methods to set each property that matches the data coming in.

Once I made stupid mistake:
Named controller argument 'action' - and on post it allways null.
[HttpPost]
public JsonResult AddMetaAction(ActionModel action)
I didn't know about that and spend on debug and solving that problem about a half of hour:(

Related

How to display complex class data in ASP.NET Core

This is my complex class
namespace EnergaticWebApp.Models
{
public class MyModel
{
public string MyString { get; set; }
public int MyInt { get; set; }
public bool MyBoolean { get; set; }
public decimal MyDecimal { get; set; }
public DateTime MyDateTime1 { get; set; }
public DateTime MyDateTime2 { get; set; }
public List<string> MyStringList { get; set; }
public Dictionary<string, Person> MyDictionary { get; set; }
public MyModel MyAnotherModel { get; set; }
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
}
And this is my action method in which I want to display my complex class data
public IActionResult Privacy()
{
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true
};
var folderDetails = Path.Combine(Directory.GetCurrentDirectory(), $"wwwroot\
{"json\\my-model.json"}");
var jsonString = System.IO.File.ReadAllText(folderDetails);
// var jsonString = File.ReadAllText("my-model.json");
var jsonModel = JsonSerializer.Deserialize<MyModel>(jsonString, options);
var modelJson = JsonSerializer.Serialize(jsonModel, options); //not in use
return View(jsonModel);
}
}
Everything is working fine except when I am returning my jsonModel in view I get an error:
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'EnergaticWebApp.Models.MyModel', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.List`1[EnergaticWebApp.Models.MyModel]'
Any suggestions of how to do this?
The error is pretty clear - you pass MyModel into the view (jsonModel); but the view expects List<MyModel> instead. They have to match!
Try to change your model in the Privacy view
#model EnergaticWebApp.Models.MyModel
InvalidOperationException: The model item passed into the
ViewDataDictionary is of type 'EnergaticWebApp.Models.MyModel', but
this ViewDataDictionary instance requires a model item of type
'System.Collections.Generic.List`1[EnergaticWebApp.Models.MyModel]'
This error message means your view needs type of List<MyModel> but you pass type of MyModel in backend.
The first way is to change your view required model, but this way may cause you need change a lot for your html code:
#model EnergaticWebApp.Models.MyModel
The second way is to change your return model to List<MyModel>.You can create an instance for List<MyModel> and add your jsonModel to it:
var jsonModel = JsonSerializer.Deserialize<MyModel>(jsonString, options);
var data = new List<MyModel>(); //add this..
data.Add(jsonModel);
return View(data);
when am converting into list: var jsonModel = JsonSerializer.Deserialize<List>(jsonString, options); its give me this error now: The JSON value could not be converted to System.Collections.Generic.List`1[EnergaticWebApp.Models.MyModel]. Path: $ | LineNumber: 0 | BytePositionInLine: 1
Only your json like below can be deserialized to List<MyModel>. If you allow changing the json, you can use the third way(var jsonModel = JsonSerializer.Deserialize<List<MyModel>>(jsonString, options);)
[
{
"MyString": "sad",
"MyInt": 1
//more properties...
}
]

Ajax post model to controller action

In mvc4 i am trying to Post model data from view to controller using Jquery Ajax but don't now what's wrong with this code can any one help me in this matter.
<script src="~/Scripts/jquery-1.8.2.js"></script>
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#save").click(function () {
$("#content").html("<b>Please Wait...</b>");
var dataObject = {
empid: 1,
EmployeeName: "rizwan",
Address: "lahore",
Country: "pakistan",
Salary: "35000.00",
DepartmentName: "Field"
}
$.ajax({
type: "POST",
url: "/Home/Index",
data: dataObject,
success: function (data)
{
$("#empname").val(''),
$("#empadd").val(''),
$("#empcountry").val(''),
$("#empsalary").val(''),
$("#empdeptname").val(''),
$("#content").html("<div class='success'>"+data+"</div>")
},
error: function (ehr)
{
$("#content").html("<div class='failed'>Error! Please try again</div>");
},
})
});
});
</script>
This is my controller action code who just receive the value of object and save into database
Problem is that i failed to receive values at controller action side.
Please help me.....
[HttpPost]
public ActionResult Index(userview dataObject)
{
department dept = new department();
employee emp = new employee();
string message = "";
try
{
emp.employeeName = dataObject.EmployeeName;
emp.address = dataObject.Address;
emp.country = dataObject.Country;
emp.salary = dataObject.Salary;
dept.departmentName = dataObject.DepartmentName;
db.employees.Add(emp);
db.departments.Add(dept);
db.SaveChanges();
}
catch(Exception ex)
{
message = "Error! Please try again";
}
if (Request.IsAjaxRequest())
{
return new JsonResult { Data = message, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
ViewBag.message = message;
return View();
}
This is my model class
public class userview
{
public int empId { get; set; }
public string EmployeeName { get; set; }
public string Address { get; set; }
public string Country { get; set; }
public decimal Salary { get; set; }
public string DepartmentName { get; set; }
}
Try using JSON.stringify
$.ajax({
type: "POST",
url: "/Home/Index",
data: JSON.stringify(dataObject), //Here is the change
success: function (data)
{
$("#empname").val(''),
$("#empadd").val(''),
$("#empcountry").val(''),
$("#empsalary").val(''),
$("#empdeptname").val(''),
$("#content").html("<div class='success'>"+data+"</div>")
},
error: function (ehr)
{
$("#content").html("<div class='failed'>Error! Please try again</div>");
},
})
You can implement BindModel yourself! get the json string and deserialize to your entity.
public class JsonBinder<T> : System.Web.Mvc.IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
using (var reader = new System.IO.StreamReader(controllerContext.HttpContext.Request.InputStream))
{
//set stream position 0, maybe previous action already read the stream.
controllerContext.HttpContext.Request.InputStream.Position = 0;
string json = reader.ReadToEnd();
if (string.IsNullOrEmpty(json) == false)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
object jsonData = serializer.DeserializeObject(json);
return serializer.Deserialize<T>(json);
}
else
{
return null;
}
}
}
}
and set the JsonBinder to the post method like
[HttpPost]
public ActionResult Index([ModelBinder(typeof(JsonBinder<userview>))] userview dataObject)
{
}
the other solution
I found that you could set DataContract to the class of Model, and set DataMember to the Properties of the class.
edit the class like this
[DataContract]
public class userview
{
[DataMember]
public int empId { get; set; }
[DataMember]
public string EmployeeName { get; set; }
[DataMember]
public string Address { get; set; }
[DataMember]
public string Country { get; set; }
[DataMember]
public decimal Salary { get; set; }
[DataMember]
public string DepartmentName { get; set; }
}
and you should add library reference "System.Runtime.Serialization"
Hope it works for you.

Having issue while trying to pass two model to the same view at a time in mvc 3

I'm trying to create my profile type page for my simple blog site. I have two simple model class like this:
public class UserInfoModel
{
public string UserName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
}
public class NewPost
{
public string PostTitle { get; set; }
public string PostStory { get; set; }
}
I have created a joint model class of user & post to pass to view like this:
public class UserPostModel
{
public UserInfoModel User { get; set; }
public NewPost Post { get; set; }
}
The methods I wrote to retrieve the user & post info are like this:
public int GetUserID(string _UserName)
{
using (var context = new TourBlogEntities1())
{
var UserID = from s in context.UserInfoes
where s.UserName == _UserName
select s.UserID;
return UserID.Single();
}
}
public UserInfo GetUserDetails(int _UserID)
{
using (var context = new TourBlogEntities1())
{
var UserDetails = (from s in context.UserInfoes
where s.UserID == _UserID
select s).Single();
return UserDetails;
}
}
public Post GetUserPosts(int _UserID)
{
using (var context = new TourBlogEntities1())
{
var entity = (from s in context.Posts
where s.UserID == _UserID
select s).Single();
return entity;
}
}
And finally I'm calling all my method from my controller action like this:
[Authorize]
public ActionResult MyProfile()
{
var Business = new Business();
var UserID=Business.GetUserID(User.Identity.Name);
var UserEntity=Business.GetUserDetails(UserID);
var PostEntity=Business.GetUserPosts(UserID);
var model = new UserPostModel();
model.User.UserName = UserEntity.UserName; // problem showing here
model.User.Email = UserEntity.Email;
model.Post.PostTitle = PostEntity.PostTitle;
model.Post.PostStory = PostEntity.PostStory;
return View("MyProfile",model);
}
A run time error showing like " object is not referenced to a object type or null object". I worked ok in a very similar way while passing single model. Whats I'm doing wrong here?
Modified your UserPostModel
public class UserPostModel
{
public UserPostModel()
{
User = new UserInfoModel();
Post = new Post();
}
public UserInfoModel User { get; set; }
public NewPost Post { get; set; }
}
NOTE: check each value before set to model it should not be null.

How to Prevent some model attributes from Update?

I'm using Scaffolding in ASP.Net, I've a Model called "Page" which has attributes as follows
public class Page
{
private DateTime _Created_at = DateTime.Now;
private bool _IsActive = true;
public int ID { get; set; }
public string Code { get; set; }
[Required]
[DisplayName("Parent Code")]
public string ParentCode { get; set; }
[Required]
public string Title { get; set; }
************
}
Here, During Create Method, I'm updating Code attributes as follows
public ActionResult Create(Page page)
{
if (ModelState.IsValid)
{
page.Code = page.Url.Replace(" ", string.Empty);
page.IsActive = true;
db.Pages.Add(page);
db.SaveChanges();
return RedirectToAction("Details", new { id = page.ID });
}
return View(page);
}
Now, Problem is, I don't want this Code value change during Update method, I'm not included it in Edit form. But still it's updating 'NULL' value if I update.
I tried [Bind(Exclude = "Code")] for Page class, But no use.
You need a hidden field for code in your edit view. Use #Html.HiddenFor(model => model.Code).

How to write a query to get data from entity datamodel?

I want get data from one of my models. I am using Entity datamodel where I have some tables in my Entity model. I want to select data from EmployeeTable.
EmployeeTable
----------------
[EmpId]|[Empname]|[EmpAddress]
I want to select [EmpID] and [Empname] columns from table. I don't know how to do this in Entity Framework and I have to return the data as JSON.
I had tried this methods but I am not geting the data.
How can I write the linq query?
public ActionResult Index()
{
return View();
}
public JsonResult GetData()
{
int Param1;
Param1 = 1;
DataEntitiesModel data = new DataEntitiesModel();
//var procedure=db.Database.SqlQuery<DataEntitiesModel>("ResourceReports #EmployeeID",new SqlParameter("#EmployeeID", Param1) );
//var procedure = db.Database.SqlQuery<DataEntitiesModel>("Select * from EmployeeDetails");
return Json(procedure,JsonRequestBehavior.AllowGet);
}
Here's the model:
public class DataEntitiesModel
{
public Int16 EmpID{ get; set; }
[Required(ErrorMessage = "Title is required")]
public string EmpName{ get; set; }
[Required(ErrorMessage = "Description is required")]
public string Description { get; set; }
[Required(ErrorMessage = "Version is required")]
public string EmpAddress{ get; set; }
}
public class DataEntitiesDBContext : DbContext
{
public DbSet<DataEntitiesModel> ProjectReports { get; set; }
}
Here's a nice video from Pluralsight to get you started with Entity Framework. You generate a data context from your database and then query this context:
public ActionResult GetData()
{
using (var db = new DataEntitiesDBContext())
{
var result = db.ProjectReports.ToList().Select(e => new {
Id = e.EmpID,
Name = e.EmpName
});
return Json(result, JsonRequestBehavior.AllowGet);
}
}

Resources