I'm trying to figure out how to use a ViewModel to view details in a view.
I have a view model set up but can't seem to use it in my views.
In my controller I have a Details method that I want to use to display all the details in the ViewModel.
So far I am passing in a username as a string and then creating a new instance of the ViewModel, I am then trying to populate the ViewModel with data but am not sure how I need to do this. I am assigning the username based on the id coming in -
public ViewResult Details(string id)
{
var viewModel = new RegisterViewModel();
viewModel.UserName = id;
return View(viewModel);
}
and then sending the viewModel back to the view, but how do I get the other related data into the viewModel??
What you need to do is query your database and pull the related information into your view model before passing it back to your view i.e.
public ViewResult Details(string id)
{
var entity = // pull record from DB by id
return View(new RegisterViewModel()
{
UserName = id,
AnotherProperty = entity.AnotherProperty
...
});
}
If your mapping view models to models in a lot of places you might want to consider using AutoMapper, it will simplify your code.
Related
I've been looking at some of the answers on this site about saving model data to session but none seem to work for me, or most likely I am not understanding it correctly and not sure how to implement it.
This is the latest solution I've been trying.
c# - How to save object to session in ASP.NET
In the Index I get an error on declaring the model telling me User doesn't exist
Model
public class User
{
public int Id { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
Controller
public ActionResult Index()
{
using (DefaultConnection db = new DefaultConnection())
{
var model = from u in db.Users select u;
var vm = (User)Session["User"];
return View(vm);
}
}
View
#model User
#Model.Username
I am not quite sure what you are trying to achieve here. But i can see some problems in your code
var vm = (User)Session["User"];
You are trying to access a session variable with key User and trying to cast it to a User instance. That means, Before executing this code, you should be setting a valid user object to Session["User"]. If you do not do that, your casting will fail(code will crash) because Session does not have any item for the key "User"
If you haven't set it yet, Before accessing this session object, you should set a valid User object to session.
var us = new User { Id=1, Username="test"};
Session["User"] = us;
Later, before accessing from session item, you should always check whether it is null or not
User u = null;
if(Session["User"]!=null)
{
u = Session["User"] as User;
// you may use u now.
}
Also, you are querying from the Users table and selecting the records to the variable model. But you are not using that anywhere in your code. I am not sure why you want to do that.
I am not sure why you are using session. If you are trying to pass data between your action method to view, there are other better solutions like using a viewmodel (preferred), ViewBag etc.
Remember Session data is available across the entire application for the current session., not just one page. Use it wisely.
In order to save your model to the Session, you need to set the session object first e.g.
using (DefaultConnection db = new DefaultConnection())
{
var model = from u in db.Users select u;
Session["User"] = model; //Part where you set / save into the session
var vm = Session["User"] as User; //Part where you retrieve into the session
return View(vm);
}
User user = Session["User"] as User;
if ( user == null) user = new User();
If you want to access your ViewModel on the view, you can do it in many ways one way is to associate your view to a model (known as strongly typed views). You can do this in your view:
#model type #*Associate your view to a ViewModel, where type is your ViewModel Class*#
<h1>#Model.Name</h1> #*access the properties of your view using #Model *#
#model is used to associate a model to a view while #Model is used to access the associated model of a view. I suggest you read first on how ASP.NET MVC works. You may visit the ASP.NET MVC tutorial on views
How to add a query string from surface controller in umbraco mvc . This is my current code.
Initially I wrote a code like
public ActionResult Registration(RegisterModel model)
{
//Code to insert register details
ViewBag.Success="Registered Successfully"
return CurrentUmbracoPage();
}
with this I could successful persist my ViewBag and model properties value but I could not add a query string with it.
For certain requirement I have to change the code that returns a url with querystring.
which I did as below
public ActionResult Registration(RegisterModel model)
{
//Code to insert register details
ViewBag.Success="Registered Successfully"
pageToRedirect = AppendQueryString("success");
return new RedirectResult(pageToRedirect);
}
public string AppendQueryString(string queryparam)
{
var pageToRedirect = new DynamicNode(Node.getCurrentNodeId()).Url;
pageToRedirect += "?reg=" + queryparam;
return pageToRedirect;
}
and with this my values of the properties in model could not persist and the ViewBag returned with null value.
Can any one suggest me how to add query string by persisting the values in the model and ViewBag.
Data in ViewBag will not be available on the View when it redirects. Hence you have to add message in TempData which will be available in the View after the redirect like TempData.Add("CustomMessage", "message");
I'm just learning MVC3 now and this is really confusing me.
I have a ViewModel that contains some child ViewModels. Each of the ChildViewModels get rendered with a different Partial View, and when submitting execute a different action on the Controller. All the ChildViewModels should perform some custom validation on their data, and if successful it should move on to the next page. If the validation fails, it should simply return to the ParentView and display the errors.
[HandleError]
public class MyController: Controller
{
public ActionResult Index()
{
var viewModel = new ParentViewModel();
return View("ParentView", viewModel);
}
[HttpPost]
public ActionResult ChildViewModelB_Action(ChildViewModelB viewModel)
{
if (ModelState.IsValid)
{
return View("ChildViewModelB_Page2", viewModel);
}
else
{
// I'm having trouble returning to the ParentView and
// simply displaying the ChildViewModel's errors, however
// discovered that creating a new copy of the VM and displaying
// the ParentView again shows the existing data and any errors
// But why??
var vm = new ParentViewModel();
return View("ParentView", vm);
}
}
}
For example,
The page loads with 3 options.
User selects option B and fills out a form.
Upon submit, the child ViewModel B gets validated and fails.
Page returns to ParentView, with ChildB all filled out, however ChildB errors are now also showing.
Why does creating a new copy of the ParentViewModel display the ParentView with the same data as the original ParentViewModel?
And is there a different way I should be returning to the ParentView after doing server-side validation?
You need to clear the modelstate if you intend to modify values in your POST action
else
{
ModelState.Clear();
var vm = new ParentViewModel();
return View("ParentView", vm);
}
The reason for that is because Html helper such as TextBoxFor will first look in the modelstate when binding their values and after that in the model. And since the modelstate already contains the POSTed values, that's what's used => the model is ignored. This is by design.
This being said the correct thing to do in your case is to simply redirect to the GET action which already blanks the model and respect the Redirect-After-Post pattern:
else
{
return RedirectToAction("Index");
}
Why does creating a new copy of the ParentViewModel display the
ParentView with the same data as the original ParentViewModel?
Because the values of the fields are retrieved from the POSTed form and not from the model. That makes sense right? We don't want the user to show a form filled with different values from what they submitted.
So lets suppose we have an action in a controller that looks a bit like this:
public ViewResult SomeAction(int id)
{
var data = _someService.GetData(id);
...
//create new view model based on the data here
return View(viewModel);
}
What I m trying to figure out is the best way to render a diferent view based on the type fo the data.
the "_someService.GetData method returns an data that knows its out type (ie not only you can do typeof(data) but also you can do data.DataType and you ll get an enum value
so I could achieve what I m trying to do doing something kinda like this
public ViewResult SomeAction(int id)
{
var data = _someService.GetData(id);
//mapping fields to the viewModel here
var viewModel = GetViewModel(data);
swtich(data.DataType)
case DataType.TypeOne: return View("TypeOne", viewModel); break;
...
}
But this does not seem to be the nicest way, (I dont event know if it would work)
Is this the way to go?
Should I use some sort of RenderPartial Aproach? after all , waht will change in the view is mostly the order of the data (ie the rest of the view would be quite similar)
Cheers
Try this:
public ViewResult SomeAction(int id)
{
var data = _someService.GetData(id);
var viewModel = GetViewModel(data);
return View(data.GetType().Name, viewModel);
}
Then just name your views accordingly.
I have a form, when user submit the form, I want to direct the user the new view to display the submitted result(transfer viewmode data to display view).
public class HomeController : Controller
{
private MyViewModel _vm;
.....
// POST: /Home/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(MyViewModel vm){
//.....
//set up vm to temp data _vm
_vm = vm;
return RedirectToAction("DisplayData");
}
// GET: /Home/DisplayData
public ActionResult DisplayData()
{
//get temp data for display
return View(_vm);
}
}
When I posted the form, I can create vm and put it to temp data place _vm. But this _vm can be sent to another action DisplayData, it's null in action DisplayData(). It seems that when redirect action even in same controller, _vm is lost although it is Controller var, not action method var.
How to resolve this problem?
It creates a new instance of the controller as it is a new request therefore as you have found it will be null.
You could use TempData to store the vm, TempData persists the data for 1 request only
Good explanation here
One good way is to call
return DisplayData(_vm)
instead of
RedirectToAction("DisplayData")
DisplayData should accept a model anyway.