ASP.NET MVC Ajax form not routing values - c#

This is a sister question from another question I posted (here). Many thanks to #nurdyguy and all of the people who helped me previously. However, I am having an issue where I am unable to pass a list of values to a destination controller that's in another View. My desired output is to send over the complete List object but right now I am getting a value count of zero (0) when it gets to the controller.
Here is my Model:
using System.Collections.Generic;
namespace Foo.Models
{
public class FooViewModel
{
public List<Foo> FooCollection = new List<Foo>();
/*Contains two properties
string CarName {get; set;}
string Color {get; set;}
List<Features> Features = new List<Features>();
*/
}
}
My View
#model Foo.Models.FooViewModel
#{
var RedCars = Model.FooCollection.Where(c => c.Color == "Red").ToList();
... //{yellow, blue, green}
}
<div id="FooCollection">
<section class="no-padding-top no-padding-bottom">
<div class="container-fluid">
<div class="public-user-block block">
<div class="row d-flex align-items-center">
<!--Red Cars-->
#using (Ajax.BeginForm("../Bar/Index/Red", null,
new AjaxOptions
{
HttpMethod = "post",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "CarsList"
}, new { id = "RedCarsForm" }))
{
<input type="hidden" name="Cars" value="#RedCars" />
<div id="status-container" class="col-lg-3 d-flex align-items-center">
<button type="submit">#RedAlerts.Count</button>
<strong>Red Cars</strong>
</div>
}
<!-- same structure for yellow, green, blue --!>
</section>
</div>
My Controller:
public ActionResult Index()
{
foreach (var car in db.database.Db_GetCars())
{
model.FooCollection.Add(new Foo()
{
CarName = car.CarName,
Color= car.Color
});
}
return View(model);
}
Destination Controller:
namespace Foo.Controllers
{
public class BarController: Controller
{
BarViewModel model = new BarViewModel();
[HttpPost, Route("/Bar/Index/{color}")]
public ActionResult Index(List<Foo> Cars)
{
//logic goes here
return View(model);
}
}
}
I spent some time digging around the best practices to route data but most places I've went have their forms set up like mine and it seems to work (for them). I even passed (as the second parameter) new { Cars = RedCars } but I still get zero (0). Is there something I am missing? Many thanks in advance!

Related

Render whole page with PartialView (and data) on page load

Currently we have a page where you select some parameters and click on a button to load data and display it in a grid, but there is no functionality to display the data on page load (via url parameters) yet. I've added the necessary routing configurations and Action, but I'm having troubles to render the page, it only displays the PartialView without styles.
How can I get the whole page to render and not just the PartialView?
Below is my simplyfied code for the View and Controller.
Views/Planing/Index.cshtml
#model PlaningTool.Web.Models.PlaningViewModel
<div class="row">
<div>
#using (Ajax.BeginForm("GetDataRows",
"Planing",
new AjaxOptions
{
HttpMethod = "Get",
UpdateTargetId = "gridPlaceholder",
LoadingElementId = "loadingIndicator"
}))
{
<!-- some comboboxes to select project and year -->
<input type="submit" value="Load data" />
}
</div>
</div>
<div id="gridPlaceholder">
<div id="loadingIndicator" style="display: none;">
<img src="~/Content/images/loading-image.gif" />
</div>
</div>
Controllers/PlaningController.cs
public partial class PlaningController : Controller
{
public virtual ActionResult Index()
{
return View();
}
public virtual ActionResult Plan(long projectID, int year)
{
var viewModel = new PlaningViewModel
{
ProjectID = projectID,
Year = year
};
// return GetDataRows(viewModel);
return RedirectToAction("GetDataRows", viewModel);
}
[RestoreModelStateFromTempData(typeof(PartialViewResult))]
public virtual PartialViewResult GetDataRows(PlaningViewModel viewModel)
{
// Load data from database with viewModel.ProjectID
// and viewModel.Year as parameters
[...]
var vm = new PlaningViewModel
{
// Set ViewModel for loaded data
[...]
};
return PartialView("Shared/_PlaningViewModelRows", vm);
}
[...]
}
I finally found a solution. I'm pretty sure it's not the best way to do this but it works.
If the Model is already set I render the PartialView.
<div id="gridPlaceholder">
#{
if (Model != null)
{
Html.RenderPartial("Shared/_PDataViewModelRows", Model);
}
}
<div id="loadingIndicator" style="display: none;">
<img src="~/Content/kendo/Bootstrap/loading-image.gif"/>
</div>
</div>
And in my Controller I've changed to this, so my ViewModel gets loaded independently and I simply return the same view as I would for Index with the new ViewModel.
public virtual ActionResult Plan(long projectID, int year)
{
var viewModel = new PlaningViewModel
{
ProjectID = projectID,
Year = year
};
return View("Index", LoadViewModel(viewModel));
}
public PlaningViewModel LoadViewModel(PlaningViewModel viewModel)
{
// Load data from database with viewModel.ProjectID
// and viewModel.Year as parameters
[...]
var vm = new PlaningViewModel
{
// Set ViewModel for loaded data
[...]
};
return vm;
}

Sending a phrase (variable) from searcher (from view) to controller, asp.net mvc

I'm trying to create searcher in asp.net. I'm so green about it. I'm trying to create in view and send to controller variable, which has text written in searcher. In that moment, I have smth like that -->
My question is, where and how create and send variable and give her data written in searcher?
Layout
form class="navbar-form navbar-left" role="search">
#using (Html.BeginForm("Index", "Searcher", FormMethod.Post, new { phrase = "abc" }))
{
<div class="form-group">
<input type="text" class="form-control" placeholder="Wpisz frazę...">
</div>
<button type="submit" class="btn btn-default">#Html.ActionLink("Szukaj", "Index", "Searcher")</button>
}
</form>
Controller
public class SearcherController : ApplicationController
{
[HttpGet]
public ActionResult Index(string message)
{
ViewBag.phrase = message;
getCurrentUser();
return View();
}
}
View
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<ul>
<li>#ViewBag.message</li>
</ul>
You're missing a key part of MVC -> the Model.
Let's create one first:
public class SearchModel
{
public string Criteria { get; set; }
}
Then let's update your "Layout" view (don't know why you had a form in a form?):
#model SearchModel
#using (Html.BeginForm("Index", "Searcher", FormMethod.Post, new { phrase = "abc" }))
{
<div class="form-group">
#Html.EditorFor(m => m.Criteria)
</div>
<button type="submit" class="btn btn-default">#Html.ActionLink("Szukaj", "Index", "Searcher")</button>
}
Then your action that serves that view:
[HttpGet]
public ActionResult Index()
{
return View(new SearchModel());
}
Then your post method would be:
[HttpPost]
public ActionResult Index(SearchModel model)
{
ViewBag.phrase = model.Criteria;
getCurrentUser();
return View();
}

MVC 4 partial view causes page to become unresponsive on submit

Situation: In my C#/MVC 4 solution I am employing a view with a partial view within. The view is a form with a submit button. The partial view is with a div that is hidden, but can be displayed if the checkbox is selected.
Issue: If the partial view is hidden, the submit works normally. If the partial view is not hidden the submit causes the page to become unresponsive, if one waits the 3 plus minutes or so the submit eventually works as expected.
The code is below. Thank you in advance for your consideration. I am a novice developer, therefore all comments, suggestions and critiques are welcome.
Code:
Model
namespace MyModels
{
public class MainModel
{
public SelectListItem Things { get; set;}
public IEnumerable<OtherModel> MoreThings { get; set;}
}
}
View
//named MyView
#model MyModels.MainModel
#using MyModels
#if (Model != null){
using (Html.BeginForm("MyViewName", "MyControllerName", FormMethod.Post, new { id = "view-form" }))
{
#Html.LabelFor(model => model.things)
#Html.DropDownList("", (Selectist)ViewBag.things)
#Html.ValidationMessageFor(model => model.field1)
#Html.CheckBoxWithLabel("aNameAttribute", Model.valueAttribute.ToString(), "anIdAttribute", Model.valueAtttribue ==1, "aLabel", "a_Toggle_Class")
<div class="treeview" style="display: none;">
<fieldset>
<legend>Title</legend>
//view causing issues replaces the div below
<div id="replacedDiv"></div>
</fieldset>
</div>
<p>
<input type="submit" value="Submit" />
</p>
}
}
<script type="text/javascript">
$(document).ready(function () {
$.ajax({
url: "/MyController/MyPartialView",
contentType: "application/html; charset=utf-8",
cache: "false",
type: "GET",
datatype: "html"
})
.success(function (result) {
$('#replacedDiv").html(result);
})
});
</script>
Partial View
//named _MyPartialView
#model MyModels.MainModel
#using MyModels
#foreach (var moreThings in ViewBag.moreThings)
{
<div id="replacedDiv">
<label>
<input type="checkbox" id=#moreThings.id value=#moreThings.name />#moreThings.name </label>
</div>
}
Controller
namespace Main.Controllers
{
public class MyController
{
[HttpGet]
public ActionResult Index(MainModel model)
{
return View(model);
}
public ActionResult MyView()
{
var model = new MainModel();
return View(model);
}
public ActionResult MyPartialView(MainModel model)
{
<OtherModel> moreThings = BLotherModel.GetMoreThings();
ViewBag.moreThings = moreThings;
return PartialView("_MyPartialView", promotion);
}
[HttpPost]
public ActionResult MyView(FormCollection collection)
{
MainModel model = new MainModel();
return SaveModel(model);
}
}
}
In your ajax you are using:
$('#replacedDiv").html(result);
But your partial view contains <div id="replacedDiv"> that are generated in a loop
replace your partial view code with :
#foreach (var moreThings in ViewBag.moreThings)
{
<label>#moreThings.name </label>
<input type="checkbox" id=#moreThings.id value=#moreThings.name />
}
and it should be OK

Loop seems to yield the same value every time

I have a string array called Groups containing the following two strings
Group Alpha
Group Bravo
Controller
public ActionResult Task(TaskModel model)
{
return PartialView(model);
}
Index view which invokes my Task action
<div id="update">
#using (Ajax.BeginForm("Task", "Home", new AjaxOptions { UpdateTargetId = "update", InsertionMode = InsertionMode.Replace}))
{
<input value="Group Alpha" name="Groups"/>
<input value="Group Bravo" name="Groups"/>
<button type="submit">Submit</button>
}
</div>
My task view
#model MvcApplication4.Models.TaskModel
<div id="container">
#if (Model.Groups != null)
{
foreach (var group in Model.Groups)
{
#Html.TextBox("Groups", group, new { #id = String.Empty })
}
}
</div>
my task model
public class TaskModel : IValidatableObject
{
public Guid TaskId { get; set; }
public String Name { get; set; }
public string[] Groups { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
yield break;
}
}
This only outputs Group Alpha Group Alpha. Wheres the problem??
Sorry for not being clear before
Example project replicating the issue https://www.dropbox.com/s/s2o59cu00am3eov/MvcApplication4.zip
You POST some input fields named Groups. In the action method processing that POST, you render a partial that uses #Html.TextBox("Groups", ...).
#Html.TextBox uses the ModelState to fill the value with the previously POSTed value, based on input element name. In this case it takes the first Groups value it finds in the POST, being "Group Alpha".
Clear the ModelState (or just the Groups key) before rendering your partial view.
This:
ModelState.Clear();
ModelState.Remove("Groups");
return PartialView(model);
Works.
Next time try showing all relevant code up front, so we don't need so many comments asking you to. :-)
This is a closure problem I think. Try this code:
<div id="container">
#if (Model.Groups != null)
{
foreach (var group in Model.Groups)
{
var currentGroup = group;
#Html.TextBox("Groups", currentGroup, new {#id = String.Empty});
}
}
</div>

Strange Behavior in Razor MVC while using Html.Helpers

I am using Razor HtmlHelpers.
using the code below i tried to print the value of ViewItemDto but it always show 0 for using #Html.TextBoxFor or any #Html...For(x=>..) method.
Does anybody have a idea why this is happening?
Note - The method is returning proper value as i can debug and see the value in debug window on views side.
[DataContract]
[Serializable]
public class ViewItemDto
{
[DataMember]
public decimal ViewItemId { get; set; }
[DataMember]
public string ItemName { get; set; }
}
From Controller Return
public ActionResult Index()
{
ViewItemDto viewItem = new ViewItemDto();
viewItem.ItemName = "OldData";
viewItem.ViewItemId = 10;
return View(viewItem);
}
public PartialViewResult SaveData(ViewItemDto viewItem)
{
viewItem.ItemName = "NewData";
viewItem.ViewItemId = 100;
return PartialView("ViewUserControl1", viewItem);
}
On View ViewUserControl1
#model Testing.Models.ViewItemDto
<div id="divSave">
#using (Ajax.BeginForm("SaveData", "Home", new AjaxOptions()
{
UpdateTargetId = "divSave",
OnSuccess = "OnSuccess",
InsertionMode = InsertionMode.Replace
}))
{
#Html.TextBoxFor(x => x.ViewItemId)//Shows 10
#Html.TextBox("ID", Model.ViewItemId) //Shows proper value 100
#Html.TextBoxFor(x => x.ItemName)//Shows oldData value
<input type="submit" name="name" value="Submit" />
}
and Index.cshtml
#model Testing.Models.ViewItemDto
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
#Html.Partial("ViewUserControl1", Model);
Shouldn't you be:
return PartialView(viewItem);
instead of:
return viewItem;
By changing the code of your controller to the following it worked here:
public PartialViewResult SaveData(ViewItemDto viewItem)
{
viewItem.ViewItemId = 100;
return viewItem;
}
I was unabled to reproduce your problem, since the code provided not even compiled.

Categories

Resources