I have ViewModel, View which uses this viewmodel and controller
in view I have input fields like this:
#Html.EditorFor(model => model.TransitApplication.ApplicationDate)
and field name is TransitApplication_ApplicationDate
I want to update some data from view in database but there is one problem
controller update source
public ActionResult Update(int id, FormCollection collection)
{
string prefix = "TransitApplication";
TransitApplication transitApplication = transitApplicationRepozitory.GetById(id);
if (transitApplication == null)
return Content("Error! Not Found!");
if (TryUpdateModel(transitApplication, prefix))
{
if (ModelState.IsValid)
{
transitApplicationRepozitory.Update(transitApplication);
transitApplicationRepozitory.Save();
return RedirectToAction("Index");
}
}
return Content("Error!");
}
I want to take prefix (TransitApplication) name programmatically and not like I have
string prefix = "TransitApplication";
some advice?
Seeing that the form prefix is built using the Class Name of the Model property, what about:
if (TryUpdateModel(transitApplication, typeof(TransitApplication).Name))
This removes your magic string - although this isn't actually the property name on the model class, but I'm guessing that if you renamed class, you'd probably want to rename the referenced property on the model too - although it is a little brittle.
The alternative is you could use something like this GetPropertyInfo method which would allow you to get the property name as a string like this var propertyInfo = GetPropertyInfo(yourModelObject, u => u.UserID); - although you don't currently have an instantiated model class in your action atm.
Related
I known if I have something like /controller/action/{id} I can access id as a function parameter. But how would I access it via the view without using the viewbag?
You can pass that function parameter to the View as part of a model. The model can be staticly or dynamically typed. The example code below demonstrates how to pass the value as a property on a dynamic model.
public ActionResult Edit(string id)
{
dynamic model = new System.Dynamic.ExpandoObject();
model.Id = id;
return View(model);
}
You would access this value in the view as follows:
#Model.Id
You can parse the URL to get the ID when in the view:
var id = Request.Url.LocalPath.SubString(LastIndexOf("/",Request.Url.LocalPath)+1);
It will be put directly into the ViewBag.id or you can access it via ViewData["id"]. hey seem like the same object
I am trying to pass a modelclass store to a RenderPartial. The goal for the renderpartial is to change/set values on this (store)model. I have been trying like this:
#{ Html.RenderPartial("test", new store(){Output=""}); }
#{ Html.RenderPartial("test", new store(){Output2=""}); }
public class store
{
public string Output { get; set; }
public string Output2 { get; set; }
}
the Partial 'test' has to change the Output properties. Is it uberhaupt possible and if yes how to do this? The renderpartial contains a javascript to calculate the value of the properties.
RenderPartial is meant to get either none of the data from the parent or a part of the model.
The overloads at:
http://msdn.microsoft.com/en-us/library/system.web.mvc.html.renderpartialextensions.renderpartial(v=vs.108).aspx
Tell you object isn't a custom object but meant to be part of the Model, ex Model.Customers
Pass the required value from your model to the partial and let the partial create it's own objects.
If you really want to pass it to the partial then create a new view model for your parent view and set the Output property in your viewmodel and pass it to the partial.
Note also that the partial gets it's own copy of the data and cannot update the parents copy so that may defeat what you actually want here.
If you need some other calculate data do it in your controller prior to passing it to the view if possible.
#store st = new store(){Output="", Output2=""};
#{ Html.RenderPartial("test", new RouteValueDictionary {{"output", st.Output}, {"output2", st.Output2}}); }
How do I pass a whole model via html.actionlink or using any other method except form submission? Is there any way or tips for it?
Though it's not advisable in complex cases, you can still do that!
public class QueryViewModel
{
public string Search { get; set; }
public string Category { get; set; }
public int Page { get; set; }
}
// just for testing
#{
var queryViewModel = new QueryViewModel
{
Search = "routing",
Category = "mvc",
Page = 23
};
}
#Html.ActionLink("Looking for something", "SearchAction", "SearchController"
queryViewModel, null);
This will generate an action link with href like this,
/SearchController/SearchAction?Search=routing&Category=mvc&Page=23
Here will be your action,
public ViewResult SearchAction(QueryViewModel query)
{
...
}
No, you cannot pass entire complex objects with links or forms. You have a couple of possible approaches that you could take:
Include each individual property of the object as query string parameters (or input fields if you are using a form) so that the default model binder is able to reconstruct the object back in the controller action
Pass only an id as query string parameter (or input field if you are using a form) and have the controller action use this id to retrieve the actual object from some data store
Use session
You could use javascript to detect a click on the link, serialize the form (or whatever data you want to pass) and append it to your request parameters. This should achieve what you're looking to achieve...
I need to do late binding of a complex type with DataAnnotations within an Action if condition X is true. I cant bind everything up front in the method params as a couple of them will not exist unless X == true so Model.IsValid will be false (since it tried to bind non existant params) due to validation failing on the complex type.
MonoRail solved this by allowing you to manually bind when needed, this is the exact scenario i have so im wondering if theres something similar available in MVC3?
I cant overload the Action as it blows up with an ambiguous call, i cant post to a different action as the form is all dynamic content, so i see the only alternative is rolling my own validation / binding mechanism pulling out data annotations to validate with.... boooo :(
I think what you need is the ControllerBase.TryUpdateModel method (it has a lots of overloads).
You can use it similarly like BindObject:
Some model:
public class MyModel
{
[Required]
public string Name { get; set; }
public string Description { get; set; }
}
In the controller action:
[HttpPost]
public ActionResult UpdateModel(bool? acceptedConditions)
{
var model = new MyModel();
if (acceptedConditions ?? false)
{
if (TryUpdateModel(model))
{
//Do something when the model is valid
}
else
{
//Do something else when the model is invalid
}
}
return View();
}
I have an Action like this:
Update([Bind(Prefix = "CurrentModel")] dynamic edited)
but when I use dynamic the ModelState.IsValid always returns true so it seems like there is no validation on the dynamic object? If not, how can I solve this?
There are two cases:
You are using view models as action arguments in which case the default model binder automatically assigns the properties and sets possible errors to the model state:
public ActionResult Update([Bind(Prefix = "CurrentModel")] EditViewModel edited)
{
if (ModelState.IsValid)
{
}
...
}
You are using some weak typing with either dynamic or FormCollection in which case the default model binder doesn't kick in and doesn't perform any validation at all as it is not capable of infering your real model type. In this case you need to manually call TryUpdateModel and indicate your model type:
public ActionResult Update(dynamic edited)
{
var model = new MyViewModel();
if (!TryUpdateModel(model, "CurrentModel"))
{
// The model was not valid
}
...
}
Conclusion: using dynamic as action argument in a controller action makes very little sense.