MVC ModelState validation failing for null value - c#

If I have the following model:
public class Model
{
public int ModelID { get; set; }
public string Title { get; set; }
public DateTime Created { get; set; }
}
And the following controller method:
public ActionResult Create(Model model)
{
if (ModelState.IsValid)
{
model.Created = DateTime.Now;
// Save to DB
}
}
In the view the Created field is hidden as I want this to populate with the timestamp of when the Create controller method is called. This fails ModelState validation due to the model.Created property being null.
I don't want to make the model.Created property Nullable but I need to somehow specify that this field isn't required in the view. Can someone please advise how to accomplish this?

You'll want to exclude the Created property from binding using the [Bind] attribute, as follows:
public ActionResult Create([Bind(Exclude = "Created")] Model model)
{
....
}
It is also recommended for security reasons, as you don't want your client to set Created value for you.

Related

Accessing model value for if statement

I'm new to MVC and I'm trying to make an if statement in the controller that accesses a value from my model. For example, if I am trying to access this radio button value from my model, how would I do it?
[Required] public bool radbutton { get; set; }.
At the top, I tried 'using PasswordTool.Models'.
Then inside my method:
if(PasswordModel.radbutton)
//do something
PasswordModel
namespace PasswordTool.Models
{
public class PasswordModel
{
[Required] public string Password { get; set; }
[Required] public bool RadioButton { get; set; }
}
}
I expect the PasswordModel.radbutton to access the value of the radio button in the model, but intellisense isn't even registering that it exists.
Hi there heisenberg3481,
Welcome to StackOverflow!
To pass Model values from the View you would need to do the following:
#model PasswordModel
// - If the bellow doesn't work try removing the 'Controller' in "MemberController" - //
#using (Html.BeginForm("GetPassword", "MemberController"))
{
Html.TextBoxFor(x => x.Password);
Html.RadioButtonFor(x => x.RadioButton);
<button type="submit">
Submit
</button>
}
Then in your controller you can retrieve the data like so:
[HttpPost]
public ActionResult GetPassword (PasswordModel objModel)
{
if (objModel.RadioButton) {
// Execute action
}
return View();
}

ViewModel becomes null when passed between actions

I'm having trouble passing a viewmodel into a view. I have two views: a Search view and a GeneralForm view. Search passes search results into GeneralForm's viewmodel.
Say the GeneralForm is a complex viewmodel that holds two other viewmodels:
public class GeneralFormViewModel
{
public GeneralInfoViewModel GeneralInfo { get; set; }
public NotesViewModel Notes { get; set; }
}
public class GeneralInfoViewModel
{
[Required(ErrorMessage = "Please enter the person's name.")]
[DisplayName("Name:")]
public string Name { get; set; }
[Required(ErrorMessage = "Please enter the person's ID.")]
[DisplayName("ID:")]
public int ID { get; set; }
}
public class NotesViewModel
{ // etc.
(I set up this way in order to use multiple #Html.BeginForms on my GeneralForm view. In this way, I hope to POST and validate small sections of the entire general form, one at a time, using KnockoutJS and AJAX.)
[HttpPost]
public ActionResult Search(SearchViewModel vm)
{
var query = // do some searching
var viewmodel = new GeneralFormViewModel()
{
GeneralInfo = new GeneralInformationViewModel
{
ID = query.id,
Name = query.name
}
};
return RedirectToAction("GeneralForm", viewmodel);
}
At this point, viewmodel.GeneralInfo is not null, and the viewmodel is passed to the GeneralForm controller.
[HttpGet]
public ActionResult GeneralForm(GeneralFormViewModel model)
{
return View(model);
}
Now model.GeneralInfo is null. What conventions of MVC am I breaking by doing this, and how can I get the GeneralForm view to render the data acquired via the Search controller to the GeneralForm view?
Problem is You can't send data with a RedirectAction.
you're doing a 301 redirection and that goes back to the client.
Store it in a TempData or Session ...
See the following post:
passing model and parameter with RedirectToAction

How to get JSON object by Query string

I have to work with queries like:
Controller/Action?query ={"action":"test","id":"13037313353","pin":"452312"}
by GET.
My ViewModel:
public class ValidatePinViewModel
{
public ActionType action { get; set; }
public int Id { get; set; }
public int Pin { get; set; }
}
Controller
public JsonResult ValidateVisit(CommonViewModel model)
{
//model is null
return Json(new InvalidPin());
}
Now I got null for my view. How I can get the correct model
As there is very little supportive information on this question, I'm going to take a shot and say that you're not POSTING to an action. e.g.
[HttpPost] // <-- Make sure you define your POST action
public JsonResult ValidateVisit(CommonViewModel model)
{
...
}
A GET, as you speficy in your tags, is not going to post a model. Unless you are specifically denoting it both in where you define your form element as well as on the action itself, it will be null.
I could add a string to get object.
Something like:
public JsonResult ValidateVisit(string query)
{
ValidatePinViewModel model = Json.Deserialize<ValidatePinViewModel>(query);
return Json(new InvalidPin());
}

Remote validation doesn't pass data to action

I have model:
public class MyModel
...fields
[Remote(ActionName, ControllerName)]
public string SomeNumber { get; set; }
..fields
And have a action in ControllerName controller:
public JsonResult ActionName(string someNumber)
{...}
But when actions is invoked the parameter someNumber is allways null.
And when I try to debug it I get
GET /ControllerName/ActionName?MyModel.SomeNumber =34189736
How can I make it work?
(I can't pass whole model MyModel, and cant change MyModel.SomeNumber name of field in my view)
UPD. Input in my view:
<input data-val="true" data-val-remote-additionalfields="*.SomeNumber" data-val-remote-url="/ControllerName/ActionName" id="MyModel_SomeNumber" name="MyModel.SomeNumber" type="text" value="34189734" class="valid">
UPD solved! :)
I create new model with single field SomeNumber and use prefix:
SomeNumber([Bind(Prefix = "MyModel")]MySingleFieldModel model)
If you're using nested ViewModels, you'll need to accept the parent ViewModel as the argument in your Validation action. For example:
public class ParentViewModel
{
public UserViewModel User {get; set; }
//....
}
public class UserViewModel
{
[Remote("UniqueUsername", "Validation")]
public string Username { get; set; }
//....
}
In ValidationController:
public class ValidationController : Controller
{
public JsonResult UniqueUsername(ParentViewModel Registration)
{
var Username = Registration.User.Username; //access the child view model property like so
//Validate and return JsonResult
}
}
Try using you model as the parameter.
So that it could bind the value to it.
public JsonResult ActionName(MyModel model)
{
//...
model.SomeNumber;
//...
return Json(validationResult, JsonRequestBehavior.AllowGet)
}
public JsonResult ActionName(string SomeNumber)
{...}
I think you may need to match case on your input parameter.

Model validation with viewModel don't works

I use viewModels to communicate between my controller and my view.
To get model validation, i use a partial class like this :
[MetadataType(typeof(EvaluationValidation))]
public partial class Evaluation
{
public class EvaluationValidation
{
[DisplayName("Title of evaluation")]
[Required( ErrorMessage="Please give a title")]
public string Title { get; set; }
}
}
The Displayname is binded to view with no problem but when i try to submit the view, i get this error :
The model item passed into the
dictionary is of type
'FOOBAR.Models.Evaluation',
but this dictionary requires a model
item of type
'FOOBAR.Areas.Evaluation.ViewModels.EvaluationFormViewModel'.
This is the code used in my controller
[HttpPost]
public ActionResult Create(FormCollection formValues)
{
Models.Evaluation data = new Models.Evaluation();
if (TryUpdateModel(data, "evaluations"))
{
this.daoe.Create(data);
return RedirectToAction("Index");
}
return View(data);
}
And this is my viewModel
public class EvaluationFormViewModel
{
public FOOBAR.Models.Evaluation evaluations;
public SelectList selectlist_evaluationtypes { get; set; }
public SelectList selectlist_evaluationstatus { get; set; }
}
Have you got an idea ?
Thank's by advance
You are passing a Models.Evaluation instance to your view, which is bound to a model of another type.
Models.Evaluation data = new Models.Evaluation();
if (TryUpdateModel(data, "evaluations"))
{
// ...
}
return View(data);
If TryUpdateModel returns false (which happens when the form does not pass validation, for example), you are effectively passing data to the View, which is of type Models.Evaluation.
Try mapping it to type FOOBAR.Areas.Evaluation.ViewModels.EvaluationFormViewModel before passing it to the view.

Categories