Save DateTime value Posted from AJAX to MVC action - ajax

I am posting DateTime value as a String Via AJAX POST to MVC Action for saving this Value.
But at the Time of Saving the Value in MVC Action, I get the error message in My AJAX response as:
The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value
My AJAX POST is as,
String dateTime="2013-07-25 11:59:22 PM";
$.ajax({
type:'POST',
url:'SaveSchedule',
data:{start:dateTime},
success:function(data){ }
});
and MVC Action as,
[HttpPost]
public ActionResult SaveSchedule(DateTime start)
{
var schedule = new Schedule { StartTime = start};
db.Schedules.Add(schedule);
db.SaveChanges();
var temp = 0;
return Json(temp);
}

While using ajax function, you should be careful as they are the client side function, hence you should decalre string type parameter in your controller, and within the action convert them into the required data type by using the tryparse methods of C#.
after getting date in string parameter you will convert the date in string to datetime datatype by using datetime.tryparse method, then you will never get such errors while using ajax.

Related

MVC Controller w/ two arguments of same ViewModel type does not bind correctly

I have the following controller action:
public JsonResult AcceptChanges(RoomPricing currentData, RoomPricing lastSaveData)
{
...
}
This controller receives JSON encoded objects from my AJAX request:
$.ajax(
{
type: "POST",
url: _controllerURL,
data: JSON.stringify({ currentData: _currentData, lastSaveData: _lastSaveData }),
...
});
The AJAX request data is derived from a form in my partial view, which uses a ViewModel of type RoomPricing. Current and lastSave data are respectively the updated and stale serialized versions of the form. The purpose of these objects is to do form update checks server-side. Server-side because the RoomPricing model includes an enumerable and other junk that would make reliable update checking complex and obnoxious to perform client-side.
Now, when the controller receives the currentData and lastSaveData, it automagically creates the RoomPricing objects, BUT both objects are identical, taking on the values of currentData. To be clear: lastSaveData is created, but only in name, as its contents are identical to that of currentData (and so ignoring the data that was passed by AJAX, which I assume goes into the void).
I expect that this behavior is a side effect of MVC trying to be helpful with Model Binding. Does anyone have a suggestion for getting around this problem? Making a super-ViewModel with two RoomPricing objects to use as the controller argument did not resolve this issue.
Thanks in advance!
Edit: The current and lastSave data comes from the following JQuery code:
var $lastSaveFormData = null;
function AjaxSubmitForm() {
var $lastSaveSerialized = ($lastSaveFormData == null ? null : $lastSaveFormData)
var $form = $('#MyForm');
submitOverrideForm(
$form.serialize(), // currentData
$lastSaveSerialized, // lastSaveData
$form.attr('action'),
);
$lastSaveFormData = $form.serialize();
}
Through the above I'm able to keep a record of all changes since the last save. Although the models are somewhat complex, the size of the data being sent is quite small so I figured I'd compare the data server-side, and here we are. Last thing of note is that I've verified that at this point - JSON.stringify({ currentData: _currentData, lastSaveData: _lastSaveData } - the encoded data is as expected...currentData and lastSaveData are unique if form updates have taken place.
Edit: I just noticed something else. Here is the data being sent to the server as well as the data received server-side just prior to being bound to the model:
_currentData, # AJAX call:
"Book%5B0%5D.Author=1&Book%5B0%5D.Title=100&Book%5B0%5D.IsPaperback=false&Book%5B1%5D.Author=2&Book%5B1%5D.Title=2222&Book%5B1%5D.IsPaperback=false"
_lastSaveData # AJAX call:
"Book%5B0%5D.Author=1&Book%5B0%5D.Title=100&Book%5B0%5D.IsPaperback=false&Book%5B1%5D.Author=2&Book%5B1%5D.Title=77&Book%5B1%5D.IsPaperback=false"
JSON received server-side, just before model binding:
{"currentData": "Book[0].Author: 1,1 Book[0].Title: 100,100
Book[0].IsPaperback: false,false Book[1].Author: 2,2 Book[1].Title:
2222,77 Book[1].IsPaperback: false,false", "lastSaveData":"false"}
Its like MVC is trying to bind the distinct values to a single model, realizes it cant, and drops the 'lastSave' data. Then, when the model hits the controller, it discovers that two models are anticipated, so it uses this model for both. Why is it behaving like this and how can I fix it?
You can add another ViewModel:
public class CurrentAndLastSavedRoomPricingViewModel
{
RoomPricing CurrentData {get;set;}
RoomPricing LastSaveData {get;set;}
}
and get it in controller:
public JsonResult AcceptChanges(CurrentAndLastSavedRoomPricingViewModel data)
{
...
}
passing this model with ajax:
$.ajax(
{
type: "POST",
url: _controllerURL,
data: {data: { currentData: _currentData, lastSaveData: _lastSaveData }},
...
});
Or you can get last saved data on server from database and don't pass it from client.

Model Validation in asp .net MVC

I am developing an application where I have a form with a model "StudentListModel".
I have a button in the same page which is not a submit button. I have written an ajax function which calls an action method in the controller specified.
Now my problem is there is a textbox for the studentname ,
[StringLength(160, MinimumLength = 3)]
[Display(Name = "First Name")]
[Required]
[Remote("CheckDuplicateNames", "AddStudent")]
public string StudentName { get; set; }
None of these validations are firing.However if I make the button as submit ,these will work.
Is there any way to do model validation other than using formsubmission?
Model validation is done automatically before your ActionMethod is executed and ModelState will be populated with information about that validation. You do not need to call ValidateModel as long as you are running your Controller and ActionMethods in the default MVC lifecycle.
An action method that has parameters will have the values for parameters populated using MVC Model Binding. This means that any values posted in a Form or QueryString (and a few other sources) will be name matched to simple parameters or properties in complex parameters. Using an HTML form and the MVC HtmlHelper methods for creating input types you get the desired behavior with very little work, but as you have noted it requires a form submit to send the data.
An ajax call will also populate the model using Model Binding but it requires the fields to be sent to the ActionMethod. Using jQuery it is as simple as performing a post or get request on the buttons click event passing a JavaScript object with your model's properties on it.
$('#yourButtonId').click(function() {
var student = {};
student.StudentName = $('#StudentName').val();
$.post('#Url.Action("ActionMethodName")', student).done(function (data) {
//handle returned result from ActionMethod}
});
});
You can call model validation manually in the controller method. The syntax is simply ValidateModel(model). This validates the model based on its current property values, and populates the ModelState dictionary with any errors.
If your model does not get populated with the values, but you have got them at hand, you can populate it using UpdateModel(model, values), another method inherited from the Controller class.

how to pass date datatype in mvc3

[HttpPost]
public JsonResult GetSearchedResults(string searchedHotel)
{
var searchingHotels = clsRepository.GetSearchedResults(searchedHotel, );
return json etc etc
}
This is my Controller. Just Like String, I need to pass Date Datatype. I have A field Name in DataBase of Type Date.Now I need to pass this.how to pass a datatype DATE.?
I have a DatePicker is my main page. When i choose A date from Datepicker, that will be saved in a variable in my Jquery file. so I need to pass this variable to controller.i need to check whether selected date and date in DataBase are equal.
Just change the datatype of your action parameter to DateTime. The default modelbinder will try to convert the value of the sent request parameter to a DateTime value.
public JsonResult GetSearchedResults(DateTime myDateParameter)
{
// do whatever you want with your date
}
Make an ajax POST request to your action with the date as a parameter.
Use jQuery to make the request. See the dosc on how you can do it: http://api.jquery.com/jQuery.ajax/

RedirectToAction is swapping day and month on date

I have a controller POST action that redirects to a GET method using RedirectToAction.
return RedirectToAction(SomeActionName, new { date = someModel.someUTCDate });
I have implemented a custom model binder which parses dates using the assumed culture and timezone information, so I am intercepting this correctly. The basic steps in my problem:
POST action is called with a date/time string, which is GMT Standard Time if not specified otherwise
The custom model binder parses this date to a DateTime with a Kind of Utc, and this is bound correctly in the correct format to the model
The POST action redirects to GET using RedirectToAction with the date that was bound as UTC time on the model
MVC3 is now trying to bind a DateTime string value with the month and day swapped around
Somewhere between calling RedirectToAction and rebinding the DateTime value for the GET action, a string conversion is taking place, which appears to be swapping the month and the day around.
Is there a simple way of ensuring that the correct string conversion takes place without the overhead of having to manually convert it for each RedirectToAction call? I would really like to know where this route value to string conversion takes place and whether or not I could influence it to do the correct string conversion.
To illustrate what I have a bit better, I have a custom DateTime model binder
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
ValueProviderResult value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (value == null || string.IsNullOrEmpty(value.AttemptedValue) || value.AttemptedValue == "null")
{
return null;
}
return FormatHelper.ConvertStringFromGMT(value.AttemptedValue);
}
On redirect I am finding that the model binder's value.AttemptedValue is an incorrectly formatted string.
Well, the issue is now resolved. As far as I can tell, when MVC gets the route values for your redirect, the route values are converted to query string parameters using the invariant culture. This is just some magic that happens behind the scenes. My solution to this problem was to override the controller methods RedirectToAction and RedirectToActionPermanent (the overloads that take a RouteValueDictionary). I iterate over the RouteValueDictionary and convert any date types here using the defined culture and timezone information. Fortunately all of my controllers were already inheriting from a custom base controller so the fix was simple to implement.

How to get the data in MM/dd/yyyy format in Linq

Login authentication on my website is based on three parameters of which one is date of birth. A DatePicker is provided to the user to select the Date. The format in which the date is saved in Database is MM/dd/yyyy.
When is check for the authentication the Linq query is not returning any result as the record in Database is in MM/dd/yyyy and the value passed from the view to the controller is in dd/mm/yyyy.Hence im not getting any output.
Below is my code of what I'm doing in controller.
[HttpPost]
public ActionResult Login(LoginTable log)
{
var login = from a in db.LoginTables
where a.DOB== log.DOB
select a;
}
Also I have tried
var login = from a in db.LoginTables
where a.DOB== log.DOB.toString("MM/dd/yyyy")
select a;
but its giving error (No Overload method 'ToString()' takes 1 argument)
What can i do?
The reason this is failing is because the LINQ is translated into SQL syntax and there is no equivalent of ToString in SQL.
Given that log is a parameter to your method why not simply have:
[HttpPost]
public ActionResult Login(LoginTable log)
{
string DOBString = log.DOB.ToString("MM/dd/yyyy");
var login = from a in db.LoginTables
where a.DOB == DOBString
select a;
}

Resources