POSTing a complex Dictionary to Controller - javascript

I am attempting to post the following type to my controller.
Model
public class EmailNotificationSettings
{
public string EmailHost { get; set; }
public string EmailPassword { get; set; }
public int EmailPort { get; set; }
public string EmailSender { get; set; }
public string EmailUsername { get; set; }
public bool Enabled { get; set; }
public bool EnableUserEmailNotifications { get; set; }
public string RecipientEmail { get; set; }
public Dictionary<NotificationType, NotificationMessageContent> Message { get; set; }
}
NotificationType
public enum NotificationType
{
NewRequest,
Issue,
RequestAvailable,
RequestApproved,
AdminNote,
Test,
}
NotificationMessageContent
public class NotificationMessageContent
{
public string Subject { get; set; }
public string Body { get; set; }
}
Now all of the properties are part of my form except Message.
Here is how I plan to populate Message
View
<label for="newRequestSubject" class="control-label">New Request Subject</label>
<div>
<input type="text" class="form-control form-control-custom " id="newRequestSubject" name="newRequestSubject" value="#Model.Message.FirstOrDefault(x => x.Key == NotificationType.NewRequest).Value.Subject">
</div>
<label for="newRequestBody" class="control-label">New Request Body</label>
<div>
<input type="text" class="form-control form-control-custom " id="newRequestBody" name="newRequestBody" value="#Model.Message.FirstOrDefault(x => x.Key == NotificationType.NewRequest).Value.Body">
</div>
Javascript to Post
$('#save').click(function (e) {
e.preventDefault();
var newRequestObj = {
"Subject": $('#newRequestSubject').val(),
"Body": $('#newRequestBody').val()
};
var message = { 'NewRequest': JSON.stringify(newRequestObj) };
var $form = $("#mainForm");
var data = $form.serialize();
data = data + "&" +JSON.stringify(message);
$.ajax({
type: $form.prop("method"),
data: data,
url: $form.prop("action"),
dataType: "json",
success: function (response) {
// Do something
}
});
});
Now this is obviously the wrong way to do it as my Message property is not getting populated.
Any idea how I can POST to the controller and it update my model?
Controller if you want to see (Using NancyFX)
private Response SaveEmailNotifications()
{
var settings = this.Bind<EmailNotificationSettings>();
// settings.Message doesn't contain the new values
}

I cannot think of a way to make it work with pure HTML. The problem is you need to submit a control with the name "Message" that contain the data, then MVC mapping engine will map that control to the "Message" property of your model.
The best way I can think of is to use a JavaScript function (bound to the onsubmit event of the form) which collects the info as an array of objects and assign it to a variable called "Message" then serialize it with the rest of the form data and submit the form.

Related

Null value while trying to send a DropDownList value to an ajax function in a Modal using MVC - Entity

I'm creating a new MVC WebSite using EntityFramework and, on my _Layout.cshtml I'm calling a PartialView, which is a Modal to insert a record on a specific table.
The partial view contains the following DDL:
<div class="form-group">
#Html.LabelFor(model => model.Currency, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<select class="form-control" id="CurrencyId" name="CurrencyId">
<option value="">Select currency...</option>
</select>
</div>
</div>
It uses an autogenerated model:
using System;
using System.Collections.Generic;
public partial class Property
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Property()
{
this.Attachments = new HashSet<Attachment>();
this.BankAccountCorrienteProperties = new HashSet<BankAccountCorrienteProperty>();
this.Contracts = new HashSet<Contract>();
this.Photos = new HashSet<Photo>();
this.Renters = new HashSet<Renter>();
}
public int IdProperty { get; set; }
public Nullable<int> IdOwner { get; set; }
public Nullable<int> PropertyType { get; set; }
public string StreetName { get; set; }
public Nullable<decimal> SquareMetersSize { get; set; }
public Nullable<bool> Garage { get; set; }
public Nullable<int> PropertyStatus { get; set; }
public string ConstructionDate { get; set; }
public Nullable<short> RentOrSell { get; set; }
public Nullable<int> Currency { get; set; }
public Nullable<decimal> Price { get; set; }
public string Notes { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Attachment> Attachments { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<BankAccountCorrienteProperty> BankAccountCorrienteProperties { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Contract> Contracts { get; set; }
public virtual Currency Currency1 { get; set; }
public virtual Owner Owner { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Photo> Photos { get; set; }
public virtual PropertyType PropertyType1 { get; set; }
public virtual PropertyStatu PropertyStatu { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Renter> Renters { get; set; }
}
And to load the data into the dropdown I had to use Ajax as follows:
getDdlInfo("../Currency/ListCurrencies", function (result) {
$.each(result.data, function (key, item) {
$("#CurrencyId").append($('<option></option>').val(item.CurrencyId).text(item.CurrencyName));
});
function getDdlInfo(path, callBackFunct) {
$.ajax({
type: "GET",
url: path,
success: function (result) {
return callBackFunct(result);
},
error: function (data) {
}
});
For then sending the value to the controller, where an HTTP Post is there to send data to database:
function createProperty() {
$.ajax({
url: '../Property/CreateProperty',
type: 'POST',
cache: false,
async: true,
data: $('form').serialize(),
success: function (result) {
//TODO: Modal de propiedad cargada
}
});
My problem here is that:
1) Whenever createProperty() goes into the controller, all data is there, except for the dropdown. It gets to the controller always null, no matter if I select a value or not and...
2) Is this the correct approach for this? Am I missing something? I tried using Razor DropDownList but I couldn't find the way to do it correctly.
Thank you.
On your model the property is called Currency, so your input's name needs to match that to successfully model bind. Changing the name on the input to Currency should resolve it.
<select class="form-control" id="CurrencyId" name="Currency">

Some elements from JSON object passed to MVC controller are NULL

I am trying to pass a JSON object to my MVC controller action via POST. The controller action is called but some elements of the object are NULL. The 'ArticleKey' is there but the 'MeasureDefinitions' are NULL (see below).
Here is the object which I am trying to parse (it gets appended with more values by the user):
var articleValues = [
{
'ArticleKey': {
'ArticleNo': 'ArticleNo',
'CustomerName': 'CustomerName',
},
'MeasureDefinitions ': [
{
'DisplayIndex': 0,
'MeasureType': 'MeasureType',
'Percentage': 99.99,
'OriginalPercentage': 0
}
]
}
];
My model looks like this:
public class ArticleValuesModel
{
[Key]
public ArticleKey ArticleKey { get; set; }
public List<MeasureDefinition> MeasureDefinitions { get; set; }
public string ArticleDescription { get; set; }
public bool AddToList { get; set; }
}
public class ArticleKey
{
public string ArticleNo { get; set; }
public string CustomerName { get; set; }
}
public class MeasureDefinition
{
public long DisplayIndex { get; set; }
[Key]
public string MeasureType { get; set; }
public double Percentage { get; set; }
public double OriginalPercentage { get; set; }
}
Here is my controller action:
[HttpPost]
public ActionResult UpdateArticleValuesJson(List<Gui.Models.ArticleValuesModel> modelList)
{
return RedirectToAction("Index");
}
Here is my Ajax POST:
$('#btnSaveArticleValues').click(function() {
$.ajax({
url: "/ArticleList/UpdateArticleValuesJson",
contentType: "application/json;charset=utf-8",
dataType: "JSON",
type: "POST",
data: JSON.stringify(articleValues),
success: function() {
console.log("Saved");
},
error: function(e) {
console.log(e);
}
});
});
Can you please help me to make the 'MeasureDefinitions' list accessible in my controller?
Removing the extra spaces in my JSON object like indicated by the_lotus did help to resolve the problem.

Pass an Object from Angularjs to MVC controller and map to Class Object

I have an object in angularjs which I want to pass and map it to custom c# class in mvc controller. but whenever I am doing this class object is null completely.
$scope.Get = function () {
var EService = [{
id: $scope.Id,
servicename: $scope.ServiceName,
servicetype: $scope.ServiceType,
monthlyrental: $scope.MonthlyRental,
serviceremarks: $scope.ServiceRemarks,
servicestatus: $scope.status,
activationdate: $scope.ActivationDate,
deactivationdate: $scope.DeActivationDate
}];
$http.post('/TS/API/Insert', Service).then(function (res) {
debugger;
})
MVC Controller and Class:
[HttpPost]
public string Insert(ServicesMaster Service)
{
GIBCADBEntities gfientity = new GIBCADBEntities();
var record = "Sent"
return Json(record, JsonRequestBehavior.AllowGet);
} public class ServicesMaster
{
public string id { set; get; }
public string servicename { set; get; }
public string servicetype { set; get; }
public int? monthlyrental { set; get; }
public string serviceremarks { set; get; }
public byte servicestatus { set; get; }
public DateTime? activationdate { set; get; }
public DateTime? deactivationdate { set; get; }
}
The javascript variable/object "EService" is ok here, and when passing only the ServicesMaster object is created with null values and no data is mapped to it. I can send single string or any value from here but when sending a complete object its behaving like this.
You are passing an array from front end and fetching object from server end. just remove the "[" and "]" brace while set value to EService . Like :
$scope.Get = function () {
var Service = {};
Service = {
id: $scope.Id,
servicename: $scope.ServiceName,
servicetype: $scope.ServiceType,
monthlyrental: $scope.MonthlyRental,
serviceremarks: $scope.ServiceRemarks,
servicestatus: $scope.status,
activationdate: $scope.ActivationDate,
deactivationdate: $scope.DeActivationDate
};
$http.post('/TS/API/Insert', Service).then(function (res) {
debugger;
});
};
It should work now. :)

Passing JavaScript object to C#

I am trying to create a new row in a table I have hosted in Azure SQL Database. My front end is AngularJS with C# in .NET as the back end.
Here is my code from the front end passing the object:
var insertTicket = function (newTicket) {
return $http.post("http://localhost:50412/api/tickets", JSON.stringify(newTicket))
.then(function (response) {
console.log(response);
console.log("Insert Successful");
return;
});
And here is my backend code that receives the data and tries to add to the database:
[Route("api/tickets")]
public HttpResponseMessage Post(Ticket t)
{
TicketsRepository.InsertTicket(t);
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
return response;
}
In TicketRepisitory:
public static void InsertTicket(Ticket tick)
{
var maxID = (from ticket in dataContext.Tickets
select ticket.id).Max();
var tick = new Ticket();
tick.id = maxID + 1;
dataContext.Tickets.Add(tick);
dataContext.SaveChanges();
}
And Here is my Ticket class:
public partial class Ticket
{
//Properties
public int id { get; set; }
public string title { get; set; }
public string customer { get; set; }
public string barcode { get; set; }
public string assignedTo { get; set; }
public string category { get; set; }
public string importance { get; set; }
public Nullable<System.DateTime> openDate { get; set; }
public Nullable<System.DateTime> dueDate { get; set; }
public Nullable<System.DateTime> closedDate { get; set; }
public string comments { get; set; }
public string condition { get; set; }
public Nullable<int> workHours { get; set; }
//Relationships
public Employee Employee { get; set; }
public Employee Employee1 { get; set; }
public Equipment Equipment { get; set; }
}
I think the issue is with Post() expecting a ticket object. I have tried searching for how to receive JSON data and use that for Ticket, but with out much luck.
My Problem is that I can not create a new row. No changes are reflected in my database.
You don't need to JSON.stringify your object when POSTing data with $httpin AngularJS, just pass the object itself as the second parameter, like this:
var insertTicket = function (newTicket) {
return $http.post("http://localhost:50412/api/tickets", newTicket)
.then(function (response) {
console.log(response);
console.log("Insert Successful");
return;
});
First there is no need to call JSON.stringify() method on newticket javascript object for second paramter of $http.post() method.
Then in the web api method write a parameter of type JObject with the name newTicket to receive the posted object, and use generic version of ToObject method to convert posted data to desired type. Don't forget to use [FromBody] attribute for the method parameter. the code for webapi looks like this:
[Route("api/tickets")]
public HttpResponseMessage Post([FromBody]JObject newTicket)
{
var t = newTicket.ToObject<Ticket>();
TicketsRepository.InsertTicket(t);
HttpResponseMessage = Request.CreateResponse(HttpStatusCode.OK);
return response;
}

Getting data from an object inside an object

Hi I am just learning knockout and I am facing a problem that I can not seem to understand.
I have this object:
var studentPersonalDetails = ko.observable();
var isInitialized = false;
var vm = {
//bindable
title: ko.observable('Profile'),
dataLoading: ko.observable(false),
hasErrors: ko.observable(false),
errorMessage: ko.observable(''),
//data
profileStudentPersonalDetails: studentPersonalDetails,
//operations
activate: activate
};
return vm;
profileStudentPersonalDetails is the equivalent of this C# object from the server:
public int? StudentNumber { get; set; }
public string Supervisor { get; set; }
public bool CanEdit { get; set; }
public string PersonId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string FullName { get; set; }
And is populated from a service.My problem is that I do know how to access the data from this object so I can display it on a html view.
I have tryed this versions:
<strong data-bind="text: StudentNumber">
<strong data-bind="text: profileStudentPersonalDetails.StudentNumber">
But non seem to work.The data gets populated into the object the right way of that I am sure and I am able to acces the other fields from the data for example the title:
<strong data-bind="text: title">
And this works.
How can I access the data?
I think you want
profileStudentPersonalDetails().StudentNumber
observables are functions. To get the objects they represent, you need to call the function. You can then access the property off the result of the function.

Categories

Resources