ASP.NET MVC Passing action parameter to the view - c#

Let's say that I have a Action method like this:
public ActionResult Page(int? id)
{
}
The question is, how can I read 'id' parameter in View?

Your code won't build successfully, until you return a view like this
public ActionResult Page(int? id)
{
return View();
}
and because you want to return id to your view you can do
Simple object
public ActionResult Page(int? id)
{
return View(id);
}
Just remember to accept the new value in your view, by dong the following at the top (very first line)
#model int?
ViewModel approach
public class MyViewModel
{
public int? Id { get; set; }
//Other properties here
}
public ActionResult Page(int? id)
{
var myViewModel = new MyViewModel()
{
Id = id
};
return View(myViewModel);
}
and then in your view
#model MyViewModel

You can access parameters from Request in view as below
Request.Params["id"]

Related

How to remove ViewModel Required before sending it?

I have a view model with a "field" that is required.
public class MyViewModel
{
[Required(ErrorMessageResourceType = typeof(Global), ErrorMessageResourceName = "Required")]
public string Code { get; set; }
}
And in one of my controllers, I'm return that view model.
But, depending on some parameters, I want to remove the required.
public ActionResult Create()
{
var model = new MyViewModel();
if(something){
model.SomeThingToRemoveTheRequiredFromCode();
}
return View(model);
}
How can I remove the required from the view model in the situation where I just created the view model?
Here's an approach. Create a new model without the Required attribute
public class MyViewModelToo
{
public string Code { get; set; }
}
then in the condition, return the view using that view model
public ActionResult Create()
{
var model = new MyViewModel();
if(something){
var modelToo = new MyViewModelToo();
return View(modelToo);
}
return View(model);
}
you can remove it from model-state dictionary like this
if(something){
Modelstate.Remove("Code")
}
If you have only one field you can use this
public ActionResult Create()
{
var nmodel= new MyViewModel().fieldname;
if(something){
return View(nmodel);
}
return View(model);
}
Or you can use #using System.Web.ModelBinding; in your class
ModelState.Remove("Code");

Mvc retain values after postback

I have a simple TestController class and User model:
public class TestController : Controller
{
public ActionResult TestAction()
{
return View();
}
[HttpPost]
public ActionResult TestAction(User user)
{
return View();
}
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
This is my form:
As far as I know MVC is stateless and it does not have a viewstate concept. But after posting the data to my controller and when I return the view, all my data is there. I expect empty fields but they are all filled with the posted data. I could not understand how MVC knows the values after postback?
You Need to use ModelState.Clear()
public class TestController : Controller
{
public ActionResult TestAction()
{
return View();
}
[HttpPost]
public ActionResult TestAction(User user)
{
ModelState.Clear()
return View();
}
}
#stephen.vakil
When you return a View from an HttpPost the assumption is that you are handling an error condition. It will keep the posted data in the ModelState and re-fill the data on the page so that the user can correct it.

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.

overriding a virtual method, but with a new signature: so custom model binder can be used

I've got an abstract class with a virtual function defined:
public abstract class ContentController
{
public virtual ActionResult Index();
}
I've got a class that derives from the above base class:
public class CartController : ContentController
I need the CartController to be able to bind a cart with a custom model binder on its Index method. Something that would normally look like this:
public ActionResult Index(Cart cart)
If I just place the Index(Cart) function into the CartController class, I get this error:
The current request for action 'Index' on controller type 'CartController' is ambiguous between the following action methods:
ActionResult Index() on type CartController
ActionResult Index(Cart) on type CartController
The only solution I've come up with thus far is to rename my model binding function and redirect from the overriden Index method:
public override ActionResult Index()
{
return RedirectToAction("IndexWithCart");
}
public ActionResult IndexWithCart(Cart cart)
{
return View("Index", cart);
}
That works, but then my URL is /Cart/IndexWithCart. Is there any way to accomplish this and still have just the /Cart URL, without modifying the base class?
Yeah just setup your route to point to the IndexWithCart action when you have the /Cart URL:
routes.MapRoute(
"IndexWithCartRoute",
"Cart",
new { controller = "Cart", action = "IndexWithCart" }
);
how about (for the base controller):
public abstract class ContentController<T> : Controller
{
public abstract ActionResult Index(T item);
}
followed by (for the inherited controller):
// just for the example
public class Cart
{
public string Foo { get; set; }
}
public class HomeController : ContentController<Cart>
{
public override ActionResult Index(Cart item)
{
//var cart = new Cart {Foo = "this is my cart test"};
//return View(cart);
return View(item);
}
}
might work.
[edit] - a second way may be to try (base class):
public abstract class ContentController<T> : Controller
{
public virtual ActionResult Index()
{
return View();
}
internal ActionResult Index(T item)
{
return View(item);
}
}
and for the controller:
// just for the example
public class Cart
{
public string Foo { get; set; }
}
public class HomeController : ContentController<Cart>
{
public override ActionResult Index()
{
Cart cart = null; // new Cart { Foo = "this is my 1st cart test" };
if (cart != null)
return Index(cart);
else
return base.Index();
}
}
i'm all thunked out now :)
how about using [HttpPost] then
action 'Index' will not be ambiguous in your Base Controllor and child Controllor
[HttpPost]
public ActionResult Index(Cart cart)
{
return View(cart);
}

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