My attempt at getting JQueryValidate custom validation attributes does not seem to be working when using jquery.load. This is my code:
CreateViewModel.cs
public class CreateViewModel
{
[DisplayName("Artwork")]
public int ArtworkId { get; set; }
[AtLeastOne("selectiongroup")]
public bool IsPromo { get; set; }
[AtLeastOne("selectiongroup")]
public bool IsUpc { get; set; }
[AtLeastOne("selectiongroup")]
public bool IsCoupon { get; set; }
public SelectList ArtworkSelectList { get; set; }
}
AtLeastOneAttribute.cs
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class AtLeastOneAttribute : ValidationAttribute, IClientValidatable
{
public string GroupName { get; private set; }
public AtLeastOneAttribute(string groupName)
{
GroupName = groupName;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
yield return new ModelClientValidationRule
{
ErrorMessage = "At least one of Coupon or Upc or Promo is required.",
ValidationType = "atleastone",
ValidationParameters =
{
new KeyValuePair<string, object>("groupname", GroupName),
}
};
}
}
Page.cshtml
<form method="POST" id="signCreationForm">
<div class="container-fluid">
<div class="row">
<div class="col-lg-6">
#Html.LabelFor(model => model.ArtworkId)
#Html.DropDownListFor(model => model.ArtworkId, Model.ArtworkSelectList, "Select an Artwork")
</div>
</div>
<div class="row">
<div class="col-lg-6"></div>
<div>#Html.ValidationMessageFor(model => model.ArtworkId)</div>
</div>
<div class="row">
<div class="col-lg-10">
<label>Associated With:</label>
</div>
</div>
<div class="row">
<div class="col-lg-4">
#Html.LabelFor(model => model.IsUpc, "UPC")
#Html.CheckBoxFor(model => model.IsUpc)
#Html.ValidationMessageFor(model => model.IsUpc)
</div>
<div class="col-lg-4">
#Html.LabelFor(model => model.IsCoupon, "Coupon")
#Html.CheckBoxFor(model => model.IsCoupon)
#Html.ValidationMessageFor(model => model.IsCoupon)
</div>
<div class="col-lg-4">
#Html.LabelFor(model => model.IsPromo, "Promotion")
#Html.CheckBoxFor(model => model.IsPromo)
#Html.ValidationMessageFor(model => model.IsPromo)
</div>
</div>
</div>
</form>
#Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
$.validator.addMethod("atleastone", function (value, element, params) {
return $("[data-val-atleastone-groupname="+params+"]:checked").length > 0;
});
$.validator.unobtrusive.adapters.add("atleastone", ["groupname"], function (options) {
options.rules["atleastone"] = options.params.groupname;
options.messages["atleastone"] = options.message;
});
</script>
CallingPage.cshtml (javascript that is calling it)
$("#create-ad[data-link]").on("click", function() {
var link = $(this).data("link");
$createDialog.load(link, function() {
$createDialog.dialog("open");
$.validator.unobtrusive.parse($("#signCreationForm"));
});
});
Now, this code works in a separate project. In this project, the partial view is loaded via jquery.load() event and for some reason this causes the custom method to never execute. I know this because the alerts would normally fire off once for each attribute decorated with atleastone attribute.
Is there anything special that needs to be done on Page.cshtml when using jquery load with custom jqueryvalidate validations?
Please put your custom method in to jquery document ready;;;;;;
For I.E.
<script type="text/javascript">
$(document).ready(function(){
$.validator.addMethod("atleastone", function (value, element, params) {
alert("halp");
return $(".grouped:checked").length > 0;
});
$.validator.unobtrusive.adapters.add("atleastone", ["groupname"], function (options) {
alert("halp");
options.rules["atleastone"] = "#" + options.params.groupname;
options.messages["atleastone"] = options.message;
});
});
</script>
The suggested duplicate for this scenario answer https://stackoverflow.com/a/16105954/82333 got the first half of the problem which was that the the add $.validator.unobtrusive.adapters.add was not functioning. However, after that the rest of the code wasn't running either.
#Bhavin Solanki's comment to include the validation files on the calling page fixed the other half, which was that on submit the code was not running.
Related
I am using Multi-Select text box in my view..
Below is my code
View:
#using (Ajax.BeginForm("Multiple", "Home", new AjaxOptions { HttpMethod = "POST" }))
{
<div class="col-md-2 col-xs-2">Associated Segment</div>
<div class="col-md-4 col-xs-4">
#Html.ListBoxFor(model => model.SegmentList, new MultiSelectList(ViewBag.List, "Value", "Text", Model.SegmentList.AsEnumerable()), new { #class = "form-control tokenizationSelect2", #multiple = "multiple" })
</div>
<div class="col-md-12 col-xs-12">
<div class="pull-right" style="padding:1%;">
<button class="btn btn-sm btn-primary" id="btnSaveProbDiagnosis" type="submit" name="">save</button>
</div>
</div>
}
<link href="~/scripts/select2.min.css" rel="stylesheet" />
<script src="~/scripts/jquery-1.10.2.js"></script>
<script src="~/scripts/select2.js"></script>
<script src="~/scripts/select2.full.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$(".tokenizationSelect2").select2({
placeholder: "Your favourite car", //placeholder
tags: true,
tokenSeparators: ['/', ',', ';', " "]
});
})
</script>
Controller:
[HttpPost]
public ActionResult Multiple(ViewModal viewmoddal)
{
return View();
}
Modal:
public class ViewModal
{
public int QuestionId { get; set; }
public string question { get; set; }
public string type { get; set; }
public List<SegmentList> SegmentList { get; set; }
public List<Answer> option { get; set; }
}
Its perfectly binding data in the UI. But when I am posting the data to controller
data not going to controller.
someone please help me in this...
You need to define array of integers to bind to multi select and these will be posted to controller actions. for.e.g in your case define your model like this.
public class ViewModal
{
public int[] SelectedSegments { get; set; }
public List<Segment> SegmentList { get; set; }
}
and in view
#Html.ListBoxFor(model => model.SelectedSegments, new MultiSelectList(ViewBag.List, "Value", "Text", Model.SegmentList.AsEnumerable()), new { #class = "form-control tokenizationSelect2", #multiple = "multiple" })
I have a weird situation where we have this view model:
public class AddCommunicationViewModel
{
public Guid Id { get; set; }
public Guid ParentCommunicationGroupId { get; set; }
public Guid ParentCommunicationGroupCampaignId { get; set; }
public List<SelectListItem> CommunicationTypes { get; set; }
public CommunicationType SelectedCommunicationTypeId { get; set; }
[AllowHtml]
public string Subject { get; set; }
[AllowHtml]
public string Content { get; set; }
public string Reference { get; set; }
public bool AttachDemand { get; set; }
public int CommunicationSortingIndex { get; set; }
public string CommunicationGroupName { get; set; }
public AddCommunicationViewModel()
{
CommunicationTypes = new List<SelectListItem>();
}
}
Now, I have a very simple form (using Html.BeginForm) which posts to the controller:
#using (Html.BeginForm("UpdateSavedCommunication", "Communication", FormMethod.Post, new { id = "saveCommunication" }))
{
#Html.HiddenFor(c => c.ParentCommunicationGroupCampaignId)
#Html.HiddenFor(c => c.ParentCommunicationGroupId)
#Html.HiddenFor(c => c.Id)
<div class="form-group">
#Html.LabelFor(c => c.SelectedCommunicationTypeId)
#Html.DropDownListFor(c => c.SelectedCommunicationTypeId, Model.CommunicationTypes, new { #class = "form-control" })
</div>
<div class="div_subject form-group email">
#Html.LabelFor(c => c.Subject)
#Html.TextBoxFor(c => c.Subject, new { #class = "form-control" })
</div>
<div class="div_content form-group mb-3">
#Html.LabelFor(c => c.Content)
<div class="card-body">
<form class="form-horizontal form-bordered">
<div class="form-group row">
<div class="col-sm-12">
<textarea name="Content" id="summernote" class="summernote" data-plugin-summernote data-plugin-options='{ "height": 280, "codemirror": { "theme": "ambiance" } }'>
#Html.Raw(Model.Content)
</textarea>
</div>
</div>
</form>
</div>
</div>
<div class="div_reference form-group email">
#Html.LabelFor(c => c.Reference)
#Html.TextBoxFor(c => c.Reference, new { #class = "form-control" })
</div>
<div class="div_attachdemand form-group mb-3">
<div>
#Html.LabelFor(c => c.AttachDemand)
#Html.CheckBoxFor(c => c.AttachDemand)
</div>
</div>
<input type="submit" class="btn btn-success" value="Gem" onclick="document.getElementById('saveCommunication').submit();" />
}
The reason my "Content" variable is a bit weird, is because I user the Summernote editor. When I click the submit button all posts fine without any JavaScript errors.
However, now the weird stuff comes.
My variables: Reference and AttachDemand is NOT posted to server. Looking at Fiddler, I can see this is the post:
ParentCommunicationGroupCampaignId=00000000-0000-0000-0000-000000000000&ParentCommunicationGroupId=00000000-0000-0000-0000-000000000000&Id=2953bc1b-49e5-4f65-8159-1c53de5c82e8&SelectedCommunicationTypeId=2&Subject=&Content=++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%3Cp%3E%3Cspan+style%3D%22color%3A+rgb%280%2C+0%2C+0%29%3B%22%3EHej%C2%A0*%7CNAME%7C*.%C2%A0%3C%2Fspan%3E%3C%2Fp%3E%3Cp%3E%3Cspan+style%3D%22color%3A+rgb%280%2C+0%2C+0%29%3B%22%3E*%7CCREDITORNAME%7C*+har+bedt+os+inddrive+din+g%C3%A6ld+hos+dem.+Der+er+tale+om+en+g%C3%A6ld+p%C3%A5%3C%2Fspan%3E%3Cspan+style%3D%22color%3A+rgb%280%2C+0%2C+0%29%3B%22%3E%C2%A0%3C%2Fspan%3E%3Cspan+style%3D%22color%3A+rgb%280%2C+0%2C+0%29%3B%22%3E*%7CDEMANDLINK%7C*+kr%2C+som+du+bedes+betale.%3Cbr%3EVi+har+vedh%C3%A6ftet+kravet+i+dette+brev+p%C3%A5+e-mail.%3C%2Fspan%3E%3C%2Fp%3E%3Cp%3E%3Cspan+style%3D%22color%3A+rgb%280%2C+0%2C+0%29%3B%22%3EDet+er+vigtigt+at+du+betales+denne+g%C3%A6ld+hurtigst+muligt%2C+for+at+undg%C3%A5+at+der+p%C3%A5l%C3%B8ber+ekstra+renter+samt+en+registrering+hos+RKI+og+som+videre+konsekvens+sendt+til+fogedretten.%3C%2Fspan%3E%3C%2Fp%3E%3Cp%3E%3Cspan+style%3D%22color%3A+rgb%280%2C+0%2C+0%29%3B%22%3ESE+DIN+SAG+OG+BETAL%3A+*%7CDEMANDLINK%7C*%C2%A0%3C%2Fspan%3E%3C%2Fp%3E%3Cp%3E%3Cspan+style%3D%22color%3A+rgb%280%2C+0%2C+0%29%3B%22%3E%3Cbr%3E%3C%2Fspan%3E%3C%2Fp%3E%3Cp%3E%3Cspan+style%3D%22color%3A+rgb%280%2C+0%2C+0%29%3B%22%3EVh%3Cbr%3E%3C%2Fspan%3E%3C%2Fp%3E%0D%0A++++++++++++++++++++++++%0D%0A++++++++++++++++++++++++%0D%0A++++++++++++++++++++++++%0D%0A++++++++++++++++++++++++%0D%0A++++++++++++++++++++++++&files=
Or in a view for humans:
So my challenge is: where is my Reference and AttachDemand ?
Now, if I move these two ABOVE the content editor, they work. So it seems that the Content is breaking because it sends some pretty cool HTML.
So any idea how to "make" this work? I guess I need to somehow escape the input in some smart way? I have added [AllowHtml] on the content attribute because it will contain HTML, but more than that?
Your view has nested forms which is invalid html and not supported (and depending on the browser and version, you may see different results).
Remove the inner <form class="form-horizontal form-bordered"> surrounding the textarea to ensure all from controls are serialized and sent in the request.
I am new to MVC and I am trying to understand how this whole Model binds to a view. I understood how to display any complex object using a partial view / views but I am not able to understand how to create an object of the model using a view.
We have a card to which we can add multiple transactions on the go .
Essentially what I am trying to achieve is this view to add transactions. The Add transactions button when clicked adds a partial view to the div tag on the main page. When I hit save all these transactions have to be added to the AcctCardTransaction model and then be sent to the controller. I am not able to add the UI of my page as the site does not allow me to add it . All I am trying to do is to display a partial view that binds to the model and creates a list of transactions so that the model can be used to save to the tables.
[![Add Card # and Transactions][1]][1]
Here is the model for the Card Transactions
public class AcctCardTransaction
{
public int? LastFourAcctNumber { get; set; }
public int LastFourDigCard { get; set; }
public List<Transaction> AssociatedTransactions { get; set; }
}
Transactions:
public class Transaction
{
public bool isSelected { get; set; }
public int Amount { get; set; }
public DateTime TransDateTime { get; set; }
public string Location { get; set; }
public string Desc1 { get; set; }
public string Desc2 { get; set; }
public string Desc3 { get; set; }
}
Here is the partial view to add one transaction - on to the screen
#model UI.Data.Models.Claim.Transactions.Transaction
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="row">
<div class="col-md-1">
<br />
#Html.CheckBoxFor(model => model.isSelected)
</div>
<div class="col-md-2">
#Html.LabelFor(model => model.Amount) <label>:</label>
#Html.EditorFor(model => model.Amount)
</div>
<div class="col-md-2">
#Html.LabelFor(model => model.TransDateTime)
#Html.EditorFor(model => model.TransDateTime)
#Html.ValidationMessageFor(model => model.TransDateTime)
</div>
<div class="col-md-2">
#Html.LabelFor(model => model.Location)
#Html.EditorFor(model => model.Location)
#Html.ValidationMessageFor(model => model.Location)
</div>
<div class="col-md-2">
#Html.LabelFor(model => model.Desc1)
#Html.EditorFor(model => model.Desc1)
#Html.ValidationMessageFor(model => model.Desc1)
</div>
<div class="col-md-1">
<br />
Delete
</div>
</div>
[![enter image description here][1]][1]
Here is the view to add card # and transaction
#model AcctCardTransaction
#{
ViewBag.Title = "Add Transactions";
}
#using (Html.BeginForm("AddTransactions", "Prepaid"))
{
<script type="text/javascript">
$(document).ready(function () {
$("#btnAddTran").click(function () {
$.ajax({
url: '/Prepaid/AddOneTransaction',
contentType: 'application/html; charset=utf-8',
type: 'GET',
dataType: 'html'
}).success(function (result) {
$('#addTransDiv').append(result);
})
.error(function (xhr, status) {
alert(status);
});
});
});
</script>
<div class="form-inline bottom-left">
<div class="row">
#Html.Label("Last 4 digits of the card")
#Html.EditorFor(model => model.LastFourDigCard)
#Html.ValidationMessageFor(model => model.LastFourDigCard)
#* #Html.Partial( "~/Views/Shared/Partials/_addTransaction.cshtml")*#
<input id="btnAddTran" value="Add Transaction" class="btn btn-default pull-right" />
</div>
</div>
<br />
<div class="row" id="addTransDiv">
<hr />
</div>
<input type="submit" value="save" class="btn btn-default pull-right" />
}
Here is my simple controller . AddoneTransaction is the action that adds one transaction partial view to the view. In my httpPost AddTransactions action The model object does not return any transactions.
Here is my exact question. how do i bind these transactions Model objects that are returned from these partial views as a list to the main model object card transactions and from there return this to the controller?
[HttpGet]
public ActionResult AddTransactions()
{
AcctCardTransaction acctCardtran = new AcctCardTransaction();
return View(acctCardtran);
}
[HttpPost]
public ActionResult AddTransactions(AcctCardTransaction cardTrans)
{
return View();
}
public ActionResult AddOneTransaction()
{
Transaction nTran = new Transaction();
return PartialView("~/Views/Shared/Partials/_addTransaction.cshtml",nTran);
}
I tried a lot of find answer for this question and could not understand what others were talking about , I saw lots of posts on how to display an existing model with a list of objects , but here I want to create and not just display.
You are providing two different models to both views and expecting that they would be bound to one Model somehow and would return the single Model on post. It doesn't make any sense.
....but I am not able to understand how to create an object of the model using a view.
Also you are rendering your Partial view using custom javascript. So you have to write a JS method to find the form and build the model from all added partial views(transactions) and then post it to the server.
$('button.submitTransaction').click(function (e) {
// Sample to find all div containing all added transactions type
var form = $('#AddTransactions').find('form');
// validate the form
var v = $(form).valid();
if (v === true) {
var transactionsContainer = $('#AddTransactions').find('row');
// Loop through the transaction div container
// Find your model properties from fields
var transactions = [];
// Fill transaction related information in the array
// e.g. Find Amount's value and other properties in a Row with in the loop
var transaction = {
'Amount': Amount,
'TransDateTime': TransDateTime,
'Location': Location,
'Desc1': Desc1
}
transactions.push(transaction);
// user your actual post url here
// Data would be automatically deserialized to the model i.e. AcctCardTransaction
var jqreq = $.post('/Prepaid',
{
'LastFourAcctNumber': lastFourAccNo,
'LastFourDigCard': lastFourDigCard,
'Description': description,
'AssociatedTransactions': transactions
});
jqxhrjqreq.done(function (data) {
if (data === true) {
alert('Success!!');
} else {
onError(null);
}
});
jqreq.fail(function (e) {
onError(e);
});
}
return false;
});
This is the scenario dumbed down:
I have a class Device
[Key]
public int Id { get; set; }
[MaxLength(50)]
public String Name { get; set; }
[Required]
public Category Category { get; set; }
[Required]
public Manufactor Manufactor { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual ICollection<Status> Status { get; set; }
And a class Comment
public int ID { get; set; }
public string Content { get; set; }
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime DateCreated { get; set; }
public string Author { get; set; }
public virtual Device Device { get; set; }
As you can see an entity of device can have many comments, but one comment only has one device.
In my controller I have these two actions:
public ActionResult AddComment(int id)
{
Device device = db.Devices.Include(x => x.Comments).Where(dev => dev.Id == id).FirstOrDefault();
if (device == null)
{
return HttpNotFound();
}
return View(device);
}
[HttpPost, ActionName("CommentAdded")]
public ActionResult CommentAdded(int id)
{
Device device = db.Devices.Find(id);
db.Entry(device).State = EntityState.Modified;
db.Devices.AddOrUpdate(device);
foreach(var comment in device.Comments)
{
db.Comments.AddOrUpdate(comment);
}
db.SaveChanges();
return View("Index");
}
Up to this point everything seemed straight forward. But suddently I don't know how to create a view in which I can do these 3 things:
Display Name of the device
Display all comments
Display a textfield to add another comment
I can easily achieve 1 and 2 but I have no idea on how to add another comment and then submit the form.
AddComment.cshtml:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Device</h4>
<hr />
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.Id)
<div class="form-group">
#Html.LabelFor(model => model.Name, new { #class = "control-label col-md-2" })
<div class="col-md-4">
#Html.DisplayFor(model => model.Name)
</div>
<div class="col-md-6">
<br/>
<div class="row">
#Html.EditorFor(model => model.Comments)
</div>
#foreach (var comment in Model.Comments)
{
<div class="row">
<div class="col-md-4">
<strong>
#Html.DisplayFor(model => comment.Author)
</strong>
</div>
<div class="col-md-4">
<strong>
#Html.DisplayFor(model => comment.DateCreated)
</strong>
</div>
<div class="col-md-4">
</div>
</div>
<div class="row">
<div class="col-md-12">
<p>
#Html.DisplayFor(model => comment.Content)
</p>
</div>
</div>
}
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
The problem at hand is: what do I need to change in my view (pos. controller), to be able to add another comment to the device selected?
Something along these lines. Just need create a html form and map the form fields to the ajax function. then call the function when the form is submitted.
hopefully that helps.
[HttpPost]
public ActionResult AddComment(int id,Comment comment)
{
Device device = db.Devices.Find(id);
comment.DateCreated = DateTime.Now;
Device.Comment.Add(comment);
db.Entry(device).State = EntityState.Modified;
db.saveChanges();
return Json("Success");
}
$.ajax({
type: "POST",
url: "/AddComment",
data: { Id: '#Html.IdFor(m => m.Id)',
Comment: { Content: 'data', Author: 'Author'} },
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function (data) {
if (data == "Success") {
$('#COMMENTSDIV').append(" YOUR COMMENTS MARKUP HERE ");
}
}
});
You just need to wrap the add comment functionality in the form and post that back to the server with a corresponding action. That action can return the entire view with the new comment added if you would like.
I can't get the ObjectId for a model to return back with a value using the MongoDB csharp official library. When I submit the form that posts back to the controller, the PageID always comes back {000000000000000000000000} in the model. The HTML rendered has the valid id, that one field never comes back properly from the form post.
The html renders: <input id="PageID" name="PageID" type="hidden" value="4f83b5ccd79f660b881887a3" />
This is what I have.
Model:
public class PageModel
{
public PageModel()
{
CanEdit = false;
CancelRequest = false;
}
[BsonId]
public ObjectId PageID { get; set; }
[Display(Name = "Page URL")]
public string PageURL { get; set; }
[AllowHtml]
[Display(Name = "Content")]
public string Value { get; set; }
[Display(Name = "Last Modified")]
public DateTime LastModified { get; set; }
[BsonIgnore]
public bool CancelRequest { get; set; }
[BsonIgnore]
public bool CanEdit { get; set; }
}
Controller Post:
[HttpPost]
public ActionResult Edit(PageModel model)
{
// check to see if the user canceled
if (model.CancelRequest)
{
return Redirect(model.PageURL);
}
// check for a script tag to prevent
if (!model.Value.Contains("<script"))
{
// save to the database
model.LastModified = DateTime.Now;
collection.Save(model);
// return to the page
return Redirect(model.PageURL);
}
else
{
ModelState.AddModelError("Value", "Disclosures discovered a script in the html you submitted, please remove the script before saving.");
}
return View(model);
}
View:
#model LeulyHome.Models.PageModel
#{
ViewBag.Title = "";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm())
{
<fieldset>
<legend>Edit Page</legend>
<div class="control-group">
#Html.LabelFor(m => m.PageURL, new { #class = "control-label" })
<div class="controls">
#Html.TextBoxFor(m => m.PageURL, new { #class = "input-xlarge leu-required span9" })
#Html.ValidationMessageFor(m => m.PageURL, null, new { #class = "help-block" })
</div>
</div>
<div class="control-group">
#Html.LabelFor(m => m.Value, new { #class = "control-label" })
<div class="controls">
#Html.TextAreaFor(m => m.Value)
#Html.ValidationMessageFor(m => m.Value, null, new { #class = "help-block" })
</div>
</div>
<div class="control-group">
#Html.LabelFor(m => m.LastModified, new { #class = "control-label" })
<div class="controls">
#Html.DisplayFor(m => m.LastModified)
#Html.HiddenFor(m => m.LastModified)
</div>
</div>
#Html.HiddenFor(m => m.PageID)
#Html.HiddenFor(m => m.CancelRequest)
<div class="form-actions">
<button type="submit" class="btn btn-primary">Save Page</button>
<button type="button" class="btn btn-danger" id="cancelBtn">Cancel Changes</button>
</div>
</fieldset>
}
#section Footer {
<script type="text/javascript" src="#Url.Content("~/Content/ckeditor/ckeditor.js")"></script>
<script language="javascript" type="text/javascript">
$(document).ready(function () {
// adjust the editor's toolbar
CKEDITOR.replace('Value', {
toolbar: [["Bold", "Italic", "Underline", "-", "NumberedList", "BulletedList", "-", "Link", "Unlink"],
["JustifyLeft", "JustifyCenter", "JustifyRight", "JustifyBlock"],
["Cut", "Copy", "Paste", "PasteText", "PasteFromWord", "-", "Print", "SpellChecker", "Scayt"], ["Source", "About"]]
});
$("#cancelBtn").click(function () {
$("#CancelRequest").val("True");
$("#updateBtn").click();
});
});
</script>
}
It looks like you are sending a string value for PageID which you are expecting an object of type ObjectId.
The model binding isn't going to know how to take this string and turn it into an ObjectId. If you take a look at the ObjectId class in the MongoDriver you will see that it is pretty hairy.
We use mongodb quite a bit and for our id's we simply use strings which provide a lot of flexibility. I am not sure the use case for which you need the ObjectId class as your document Id but you may not need it.
So from here it seems like you have two options.
Change your document id's to strings or something else
Write a custom model binder for the ObjectId class
Hope that helps :)
Create Binding:
public class ObjectIdBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
return !string.IsNullOrWhiteSpace(result.AttemptedValue) ? ObjectId.Parse(result.AttemptedValue) : ObjectId.Empty;
}
}
Create ModelBinderConfig:
namespace Nasa8x.CMS
{
public class ModelBinderConfig
{
public static void Register(ModelBinderDictionary binder)
{
binder.Add(typeof(ObjectId), new ObjectIdBinder());
binder.Add(typeof(string[]), new StringArrayBinder());
binder.Add(typeof(int[]), new IntArrayBinder());
}
}
}
Register on Global.cs:
protected void Application_Start()
{
ModelBinderConfig.Register(ModelBinders.Binders);
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
If you don't need the PageID property in your C# Class to be of Type ObjectId, but want to take advantage of this Type on the MongoDB-Side, you can let the Driver take care of the conversion in your class-Definition:
public class PageModel
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string PageID { get; set; }
}