send data to and from view - c#

I have an ASP.NET MVC 5 project where I need to get a class (with approximately 20 variables) from my controller to a view, and then I need to get the data back to my controller. I know I can use ViewBag variables, but that seems so tedious for that many variables, and I don't want to use a model because the data won't necessarily come from or go to a database. Does anyone know a good way to do this?

Use a view model. Models don't have to be connected to a database. They're very handy for usage in forms. Here's a very simplified example of what you can do:
public class PersonViewModel
{
public string Name {get;set;}
public string Email {get;set;}
// .... etc
}
Load form
[HttpGet]
public ActionResult MyForm()
{
return View(new PersonViewModel());
}
Post form
[HttpPost]
public ActionResult MyForm(PersonViewModel model)
{
if (ModelState.IsValid)
{
// do stuff
}
return View(model);
}
View (bound to PersonViewModel)
#model PersonViewModel
<h1>Person Form</h1>
#using (Html.BeginForm())
{
#Html.LabelFor(m => m.Name)
#Html.TextBoxFor(m => m.Name)
#Html.LabelFor(m => m.Email)
#Html.TextBoxFor(m => m.Email)
<button type="submit">Submit</button>
}

Related

Binding Model of PartialViews on a POST

I have a complex model class like:
public class Client
{
public string Name { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string AddressLine { get; set; }
}
My View is made of several Partial's on which I pass parts of the model into them and dispose some fields for edition:
In Index.cshtml
#using (Html.BeginForm("Index"))
{
#Html.DisplayNameFor(modelItem => model.Name)
#Html.DisplayFor(modelItem => model.Name)
<div id="divAddress">
#Html.Action("_Address", model.Address)
</div>
<div>RESULT MESSAGE GOES HERE!</div>
<input type="submit" value="Submit" />
}
In _Address.cshtml
#Html.DisplayNameFor(modelItem => model.AdressLine)
#Html.EditorFor(modelItem => model.AdressLine)
On the code-behind my Actions consist of two simple ActionResults methods:
[HttpGet]
public ActionResult Index()
{
Client = new Client();
Client.Name = "António Fonseca"
return View(model);
}
[HttpPost]
public ActionResult Index(Client model)
{
return View(model);
}
public ActionResult _Address(Address model)
{
return View(model);
}
When I submit the form, I need to call a WebService with the full Client structure and display it's resulting message.
What happens is that when hitting Index(model) -> model.Address is null.
It's only bound back when it hits _Address(model) method.
Is there a way to bind the full class structure in main Action using PartialViews?
Change the model in _Address.cshtml to be the same as the model in your main view and use #Html.Action("_Address", model) so that the form controls are correctly named - i.e. name="Address.AdressLine" (its currently just name="AdressLine" but you model does not contain a property named AdressLine).
#model Client
#Html.DisplayNameFor(m => m.Address.AdressLine)
#Html.EditorFor( m=> m.Address.AdressLine)
However using #Html.Action() is not the correct approach for this. You should be using an EditorTemplate. Rename _Address.cshtml to Address.cshtml (to match the name of your class name) and place it in the /Views/Shared/EditorTemplates folder and then in the view use
#Html.EditorFor(m => m.Address)
which will correctly name your form controls.

Passing Data from View to Model in MVC in c#

I am new to ASP.NET MVC. Is it possible to pass data from view to model in mvc? this question was asked in interview.Please anyone give me right answer.
Thanks in Advance
To pass data to controller through model you should wrap all the inputs (checkboxes, textboxes, radio etc.) with <form ...> tag. You could do it using HTML tag or with help of ASP.NET MVC helper #Html.BeginForm(...). Once you submit your form, all the input data will be sent to a controller action and mapped to a targeted model. Please see an example:
Model:
public class UserModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
View:
#model UserModel
#using (Html.BeginForm("Search", "Events"))
{
#Html.TextBoxFor(m => m.FirstName)
#Html.TextBoxFor(m => m.LastName)
<input type="submit" value="Search" />
}
Controller:
public class EventsController: Controller
{
public ActionResult Search(UserModel model)
{
//do something
return View(); //return "Search" view to the user
//return View(model); //You can also return view with the model to the user
//return View("SpecificView"); //You can specify a concrete view name as well
}
}
No, we do not pass any information from view to model directly, both the view and model are different module. we can pass data, value or any information from view to model via controller.

Form sends empty model

I have a list of Objects which I want to modify on my View, I have built a View Model to contain the list of objects:
public class TrainerListViewModel
{
public List<Trainer> Trainers { get; set; }
}
and I send a list of Trainers to the view from the controller:
public virtual ActionResult Social()
{
var Trainers = new TrainerListViewModel();
Trainers.Trainers = (from t in _db.Trainers select t).ToList();
return View(Trainers);
}
and here is my view:
#model XStreamingFitness.ViewModels.TrainerListViewModel
#using (Html.BeginForm("Social", "Participant", FormMethod.Post))
{
for (int i = 0; i < Model.Trainers.Count; i++)
{
<div class="formSep">
<div class="editor-label">
#Html.LabelFor(m => m.Trainers[i].permissionPostFacebook)
</div>
<div class="editor-field">
#Html.EditorFor(m => m.Trainers[i].permissionPostFacebook)
#Html.ValidationMessageFor(m => m.Trainers[i].permissionPostFacebook)
</div>
</div>
}
<input type="submit" value="Save Settings" name="Submit" />
}
now here is the POST controller method:
[HttpPost]
public virtual ActionResult Social(TrainerListViewModel Trainers)
{
return RedirectToAction("Profile");
}
but everytime I submit, the Trainers model is empty and I am not sure why this could be happening.
This question has been asked before here at SO I suggest you check mvc3 submit model empty, its the same principals as the problem you are having.
See the snippet from the post.
I see people writing the following lambda expression modelItem =>
item.SomeProperty in their views very often and asking why the model
binder doesn't correctly bind collection properties on their view
models.
This won't generate proper name for the checkbox so that the default
model binder is able to recreate the Settings collection. I would
recommend you reading the following blog post to better understand the
correct format that the model binder expects.
-By Darin Dimitrov
It is to do with the way you are building your form he goes to suggest you use Property Editor Templates for the Trainer object.
This should then work.
Hope it helps

ASP.Net MVC3 missing model properties

I am new to MVC3 and am trying to write a blog application as a learning tool.
I've created a database object for the blog post and generated a controller using the Controller with Read/Write actions and views using Entity Framework to control the entity.
I'm having troubles with the edit commands. There are about 6 properties for a blog post but I only want to allow the edit to modify the title and content of the post. My code is as follows:
public ActionResult Edit(int id)
{
blog_Post blog_post = db.blog_Post.Find(id);
return View(blog_post);
}
//
// POST: /Post/Edit/5
[HttpPost]
public ActionResult Edit(blog_Post blog_post)
{
if (ModelState.IsValid)
{
db.Entry(blog_post).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(blog_post);
}
#model BlogVersion1._0.blog_Post
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>blog_Post</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PostContent)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PostContent)
#Html.ValidationMessageFor(model => model.PostContent)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
The problem that comes about is in the public ActionResult Edit(blog_Post blog_post) method. In the Edit(int id) method, I have put a breakpoint in and I can see that blog_post is being properly passed to the view (including all of its properties populated).
But the blog_post being returned to the [HttpPost] method is missing properties for UserId, DateCreated, etc. An exception is obviously thrown on the db.SaveChanges call as required foreign keys are missing.
How do I ensure that all properties are returned to the second edit method to properly make the update?
Because you are not sending the values of those elements from your form when you do the POST ing. One way to fix this is to keep them inside the form using Hidden Variables
#using(Html.BeginForm())
{
#Html.EditorFor(model => model.Title)
#Html.HiddenFor(model => model.UserId)
<input type="submit" />
}
I think the clean solution is to "Dont use the Domain model in the view, Use a ViewModel with necessary properties for the View. In this case, obviously CreatedDate should not be something the View should supply. It should be something the code will be filled to the object.
So create a ViewModel for this
public class BlogPostViewModel
{
public int ID { set;get;}
public string Title { set;get;}
public string Description { set;get;}
}
and use this for transfering data from View to controller and viceversa
public ActionResult Edit(int id)
{
var domainObject=repo.GetPost(id);
var viewModel=new BlogPostViewModel();
viewModel.ID=domainObject.ID;
viewModel.Title=domainObject.Title;
//map other REQUIRED properties also
return View(viewModel);
}
Your view will be strongly typed to this
#model BlogPostViewModel
#using(Html.BeginForm())
{
#Html.EditorFor(model => model.Title)
#Html.HiddenFor(model => model.Description)
<input type="submit" />
}
In the POST action,map it back to the domain object and save
[HttpPost]
public ActionResult Edit(BlogPostViewModel model)
{
if(ModelState.IsValid)
{
var domainObject=new blog_Post();
domainObject.Title=model.Title;
domainObject.ModifiedDate=DateTime.Now;
//set other properties also
repo.Update(domainObject);
return RedirecToAction("Success");
}
return View(model);
}
Instead of manually mapping properties one by one you can consider using AutoMapper library which does this for you in one line of code!
Just add hidden fields for all other, non-editable properties.
#Html.HiddenFor(model => model.Id)
These field will be included in POST and hence, model binder will correctly put them into your blog_post instance.
On the other side, you should really be using view models - simple POCO classes that will be models for your views. Using entity models directly is not recommended.
Here's some info on that:
ASP.NET MVC ViewModel Pattern
http://stephenwalther.com/archive/2009/04/13/asp-net-mvc-tip-50-ndash-create-view-models.aspx
The model binder will only populate the properties that are POSTed in the HTTP request. Your view only contains Title and PostContent.
You either need to include hidden fields for each of the missing properties. Or just the ID property and then do a database lookup for the rest.
For your case, I think You should rather use the HtmlHelper extension method "EditorForModel" instead of calling "EditorFor" for each property. You are complicating your life using EditorFor on each property (and as gred84 is saying, it doesn't post the non displayed properties in the HTTP request in you context).
In your blog_Post model class you should flag each property that you don't want to be edited with the attribute [HiddenInput(DisplayValue = false)]
Then instead of all your code in the view, you can simply have (simplified - without validation summary)
#using (Html.BeginForm())
{
#Html.EditorForModel()
<input type="submit" value="Save" />
}

Simple way to get parameter from URL and place it into an input control?

I'm making an invite system where a user when registering to the site can specify a user who refereed them.
There's also a way for existing users to send invites. The friend would recieve a link:
http://www.foo.com/account/register?referal=sandyUser216
How can I get that value sandyUser216 and place it as the value inside of a text input box?
I'm using C# and MVC3.
Check the Request.QueryString.
<input type="text" value="#Request.QueryString["referal"]" />
Or put it in a Model property rather than having it in the view.
As always in an ASP.NET MVC application you start by writing a view model that will represent the information contained in your view:
public class RegisterViewModel
{
[Required]
public string Referal { get; set; }
}
then you write controller actions for respectively showing the registration form and processing it:
public ActionResult Register(RegisterViewModel model)
{
return View(model);
}
[HttpPost]
[ActionName("Register")]
public ActionResult ProcessRegistration(RegisterViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
// TODO: perform the registration
return RedirectToAction("success");
}
and finally you write the corresponding strongly typed view:
#model RegisterViewModel
#using (Html.BeginForm())
{
#Html.LabelFor(x => x.Referal)
#Html.EditorFor(x => x.Referal)
#Html.ValidationMessageFor(x => x.Referal)
<button type="submit">Register</button>
}
Now all that's left is to simply navigate to /account/register?referal=sandyUser216.
And you have accomplished the whole MVC pattern. Should you skip any of those 3 letters it means that you are doing ASP.NET MVC incorrectly.

Categories