Persist MVC3 WebGrid data - asp.net-mvc-3

I have a view model that contains an object containing a list and I'm outputting this list using a WebGrid.
The page can currently postback to multiple Actions which edit/add to this list. I'd like to persist this data across all postbacks so all Actions can act upon any changes past Actions have performed on the list. Is there anyway I can get the webgrid to bind to my model in the controller? Or am I required the list using another method like session/database?
Here's my code to help clear up what I mean.
I have a view model looking like this:
public class EggBasketViewModel {
public Basket EggBasket { get; set; } // Contains list of eggs & other basket info
public Egg EggToAdd { get; set; }
}
and I'm outputting it like this:
#model Basket.Models.EggBasketViewModel
#{
var grid = new WebGrid(Model.Eggs); // Eggs is my list of eggs
}
#using (Html.BeginForm()) {
#Html.Partial("_CreateOrEditEggBasket")
#Html.Partial("_CreateOrEditEgg")
#grid.GetHtml()
<p>
<button name="button" value="submitEgg">Add Egg</button>
<button name="button" value="submitBasket">Submit Basket</button>
</p>
}
With my controller looking like so:
[HttpPost]
public ActionResult Create(EggBasketViewModel Model, string button)
{
if (ModelState.IsValid) {
switch (button) {
case "submitEgg":
return this.submitEgg(Model);
case "submitBasket":
return this.submitBasket(Model);
default:
break;
}
} else {
return View();
}
}
public ActionResult SubmitBasket(EggBasketViewModel Model) {
eggBasketRepository.InsertOrUpdate(Model.EggBasket);
eggBasketRepository.Save();
return RedirectToAction("Index");
}
public ActionResult SubmitEgg(EggBasketViewModel Model) {
Model.EggBasket.Eggs.Add(Model.EggToAdd);
return View(Model);
}
I created it this way thinking the WebGrid would output data in a way the model binder would be able to bind it to my view model on POST and so persist any new Eggs using the html output by the WebGrid. Is there any way the WebGrid could output the list in a way compatible with the model binder? Or am I better off using a different method?
Thanks.

Related

How to Retrieve Page Hyperlinks after Requesting a URL using MVC3?

I have created a very simple view in my MVC3 project that contains a textbox that receives and validates a URL. The controller class is rather simple:
[HttpPost]
public ActionResult Save(ValidationModel model)
{
if (ModelState.IsValid)
{
//Save or whatever
}
return View(model);
}
I'm needing some guidance on how to retrieve the URL entered into the textbox, and subseuquently scan the resulting page for hyperlinks or tags. Once those tags are scanned, I need to return a new view to my user with a list or grid of the tags in alpha order.
Can anyone point me in the correct direction on above steps?
Thanks:)
In your view model you will have a property:
public class ValidationModel
{
[Required]
public string Url { get; set; }
}
and then you will have a corresponding textbox in the view:
#model ValidationModel
#using (Html.BeginForm)
{
#Html.EditorFor(x => x.Url)
<button type="submit">OK</submit>
}
and finally in your POST controller action:
[HttpPost]
public ActionResult Save(ValidationModel model)
{
if (ModelState.IsValid)
{
//Save or whatever
// use model.Url here => it will contain the user input
}
return View(model);
}
Try this:
in your view where your using your model inside your FORM:
#Html.TextBoxFor(m => m.MyHyperLink)
and in your controller you do this:
model.MyHyperLink you can manipulate the string or do what ever you want
easy as that..
hope i helped.

MVC3 :: Create a view to handle multiple types

I have a situation where I am wanting an 'Add' View to accept an int from the controller but return a different type to the HttpPost controller method. Confusing, I know. The 'Add' View is used to create an object typed as a Widget, but I need to pass in the ID of the WidgetCategory. So in my WidgetController, I would have a method something like:
public ActionResult Add(int id) // 'id' is the WidgetCategoryID
{
return View(id);
}
However, in the view, since in it's intended to return a Widget to be added would start like this:
#using MyProject.Models
#model Widget
#{
ViewBag.Title = "My Title";
Layout = "~/Views/Shared/_MyLayout.cshtml";
}
#using (Html.BeginForm())
{
// Insert markup here ...
}
My question is, how do I pass the WidgetCategoryID into the controller if it's typed to return a Widget? I was hoping to add it as a hidden field inside the form like so:
#Html.Hidden(id)
Any ideas would be greatly appreciated.
Thanks!
Assuming your ViewModel Widget has a WidgetCategoryId property
public class Widget
{
public int ID { set;get;}
public int WidgetCategoryId { set;get;}
//Other properties
}
Send that to the Add View (HttpGet)
public ActionResult Add(int id)
{
Widget objModel=new Widget{ WidgetCategoryId =id} ;
return View(objModel);
}
Now in your Add View, Keep that in a hiddden variable using the HiddenFor HTML helper method.
#using MyProject.Models
#model Widget
#{
ViewBag.Title = "My Title";
}
#using (Html.BeginForm())
{
#Html.HiddenFor(m=>m.WidgetCategoryId);
<input type="submit" value="Save" />
}
Now you will have it in your HTTPPost action method when you submit.
[HttpPost]
public ActionResult Add(Widget model)
{
// check model.WidgetCategoryId and Have fun with it
}
default model binder checks for request parameters by name and attempts to set properties on model according. If you need something more evolute, you can take a look to custom model binding. Btw, you can change your action to:
public ActionResult Add(Widget widget) // Widget class has one property named Id with public set
{
return View(widget);
}
or
public ActionResult Add(int id) // 'id' is the WidgetCategoryID
{
Widget widget = new Widget();
widget.Id = id;
return View(widget);
}
I slightly prefer the second form for creations, but I guess it's a matter of tastes
Btw, your view's form shall have inputs for each "important" property of the Widget object. (Hidden or text) via:
#Html.HiddenFor (m => m.Id);
Within your view code, you're not only specifying that the view will return a Widget type, but specifying that the entire model for that view is a Widget type. Basically, that data passed both into and out of the View via its #model is of type Widget.
What you can do here is to retain the strong-typing of the View to a Widget, but where you need to pass in simply an ID value (a simple int), you can use either the ViewData or the ViewBag
For example, in the controller:
public ActionResult Add(int id) // 'id' is the WidgetCategoryID
{
// All properties of a ViewBag are completely dynamic!
ViewBag.WidgetID = id;
// You're still returning a View strongly-typed to a Widget, but not
// actually supplying a Widget instance.
return View();
}
And in the View:
#using MyProject.Models
#model Widget
#{
ViewBag.Title = "My Title";
Layout = "~/Views/Shared/_MyLayout.cshtml";
}
#using (Html.BeginForm())
{
// Retrieve the WidgetID from the ViewBag
var WidgetID = ViewBag.WidgetID;
// Do something with the WidgetID, for example:
#Html.Hidden(WidgetID)
}
Note that ViewData and ViewBag are very similar mechanisms by which "non-model" data can be passed into a view. ViewBag is newer (MVC 3) and is based upon the dynamic features of C#4.0, whereas ViewData is the older method based upon a collection of key/value pairs.
In the Add Action in the Controller you can set a ViewBag property to the id and them in the View do html.Hidden() using the ViewBag property. I.e.,
public ActionResult Add(int id) // 'id' is the WidgetCategoryID
{
Widget widget = new Widget();
widget.Id = id;
ViewBag.categoryId = id;
return View(widget);
}
In the View
#Html.Hidden(#:ViewBag.categoryId)

Read The Data From DropDown in ASP.Net MVC3

I am doing the ASP.net MVC 3 (Empty type and not the internet type) with the Database First approach...
What i need is
Step 1:
I just used the dropdown to display the various locations where the company is located. The list comes from the Organization table and Location is only one string field in this Oranization Table,
Step 2:
While the user is doing registration, the dropdown list will show the locations.. Now, user selects India, then this value (Location Name) should store in the UserLogin Table...
Now how to read the value from the dropdown and i hope you understand my question and thanks in advance
I would use view models:
public class RegisterViewModel
{
public string LocationName { get; set; }
public IEnumerable<SelectListItem> Locations { get; set; }
}
then a controller action that will serve the view:
public ActionResult Index()
{
var model = new RegisterViewModel();
model.Locations = new SelectList(dbcontext.Organization_Details, "OName", "OLocation");
return View(model);
}
then the corresponding strongly typed view:
#model RegisterViewModel
#using (Html.BeginForm())
{
#Html.LabelFor(x => x.LocationName)
#Html.DropDownListFor(x => x.LocationName, Model.Locations)
<button type="submit">OK</button>
}
and finally the controller action that will be invoked when the form is submitted:
[HttpPost]
public ActionResult Index(RegisterViewModel model)
{
// model.LocationName will contain the selected location here
...
}

MVC3 Razor - How to pass data from controller to view - and back to controller

I have a view where everything will be populated by the user - but relates to a parent entity. I pass that Id to my view using ViewBag, but I don't know how to get it back to the post action in the controller. I have tried hidden form fields, but it isn't showing in the post, or I do not know how to grab it...
Controller:
public ActionResult AddCar(int id)
{
ViewBag.Id = id;
return View();
}
View (tried):
#using (Html.BeginForm("AddReturn", "DealerAdmin", new { id = carId }))
{
View (tried):
#Html.Hidden(carId.ToString())
HOw do I retrieve the value in my post action in my controller? Or is there a better/different way to approach it?
THanks
Create a ViewModel for post, it would be as follows
public class Post
{
int id {get;set;}
//other properties
}
and in your controller action send a post object
public ActionResult AddCar(int id)
{
Post post = new Post();
post.Id = id;
return View(post);
}
your view should use the Post class as the model
#model namespace.Post
#using (Html.BeginForm("AddReturn", "DealerAdmin", FormMethod.Post)
{
#Html.HiddenFor(model => model.Id)
}
and your controller action which expects result should have a post object as the input parameter
public ActionResult AddReturn(Post post)
{
//your code
}
The hidden field should works. The problem is that your controller did not accept it.
You can use ViewModel to achieve this. Or, use the code below in your action:
id = Request.Form["id"]
Try like this:
#using (Html.BeginForm("AddReturn", "DealerAdmin", new { id = ViewBag.Id }))
{
...
}
there some way
1. send the value with query string if there is only one value to send to the controller
2. if you want collect many field from view you can use formcollection
sample::
public actionresult method1()
{
int id = //everything you want
viewbag.id=id;
....
//and other field to collect
}
in view
<form method="post" action="method1" enctype="now i dont remeber the value of this option" >
#html.hidden("id")
.....
<input type="submit" value"Send"/>
</form>
[httpPost]
public actionresult method1(fromcollection collection)
{
int id = collection.get("id");
....
//and other field to collect
}

asp.net mvc3 updated (refresh) the viewmodel in view

I send a BOOKVIEWMODEL with fields and a simple IEnumerable in view I get the this list IEnumerable in the view by a method with JSON AJAX in view and I fill my table Ristourne(View) with JQUERY it works very well but I not know how I fill (BIND or refresh) the list IEnumerable of my BOOKVIEWMODEL in the VIEW to recovered it in the Controller:
[HttpPost]
public ActionResult Create(BookViewModel _bookViewModel)
{
if (ModelState.IsValid)
{
_bookViewModel.Ristourne
return RedirectToAction("Index");
}
return View(_bookViewModel);
my bookviewmodel
public class BookViewModel
{
public String book { get; set; }
public String price { get; set; }
public IEnumerable<Ristourne> Ristourne { get; set; }
}
For the model binding to work, you need to "mimic" the convention MVC uses when generating the form fields.
I don't know the contents of the Ristourne class, but let's say it had 1 field called Foo.
In that case, when you render out the elements (from the JSON AJAX callback), make them look like this:
<input type="text" name="Model.Ristourne[0].Foo" id="Model.Ristourne[0].Foo"/>
<input type="text" name="Model.Ristourne[1].Foo" id="Model.Ristourne[1].Foo"/>
<input type="text" name="Model.Ristourne[2].Foo" id="Model.Ristourne[2].Foo"/>
And so on. Easiest thing to do is in your AJAX callback, just use a basic for loop to create the elements indexer.
Altenatively, a cheat/easy way around this problem would be to make your AJAX action return a PartialViewResult:
public PartialViewResult Book()
{
var ristournes = _repo.Get();
var model = new BooksViewModel { Ristourne = ristournes };
return PartialView(model);
}
Then the partial view:
#Html.EditorFor(model => mode.Ristourne)
Then MVC will create the form fields correctly.
I always prefer this option over dynamically generated form fields. If you want to go down this path often, you should consider something like Knockout.js and/or Upshot.

Resources