Displaying Partial View in a View and Passing Arguments - c#

I'm trying to display two partial views in my index view. In those partial views are data grids that I want to display data when something is searched in the search box I have set up. Both of these pages work when I do them separately, but I don't know how do use them as partial views.
My View looks like this:
#using (Html.BeginForm("Index", "Home", "POST"))
{
<div class="searchField">
<div class="searchbox">
Search: <input type="text" name="heatSearch" />
<input type="submit" value="Submit">
</div>
</div>
}
<div>
#Html.Partial("PartialChemAnalysis", (string)ViewBag.SearchKey)
</div>
#Html.Partial("PartialSlag", (string)ViewBag.SearchKey)
My Controller looks like this:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(string heatSearch)
{
ViewBag.SearchKey = heatSearch;
return View();
}
public ActionResult PartialChemAnalysis(string heatSearch)
{
HomeModel C = new HomeModel();
IEnumerable<HomeModel> model = C.ChemList;
C.ChemistryDataPull(heatSearch);
return PartialView(C.ChemList);
}
public ActionResult PartialSlagView(string heatSearch)
{
PartialSlagViewModel D = new PartialSlagViewModel();
IEnumerable<PartialSlagViewModel> model = D.SlagList;
D.SlagViewDataPull(heatSearch);
return PartialView(D.SlagList);
}
Ideally what's in that search box would be passed to both views and the grids would form based on that. I'm not sure what I'm doing wrong so any help is appreciated.

I would start with this:
#{
//create your first model
HomeModel CModel = new HomeModel();
CModel.ChemistryDataPull(Model.SearchValue);
//create your other model
PartialSlagViewModel DModel = new PartialSlagViewModel();
DModel.SlagViewDataPull(Model.SearchValue);
}
#Html.Partial("PartialAnalysis", CModel)
#Html.Partial("PartialSlag", DModel)
This is assuming you've already searched, processed a postback, and you've returned the SearchValue back to your view in your model. You could return it in ViewBag.SearchValue instead I suppose and replace Model.SearchValue with ViewBag.SearchValue, but your model would be a better place to store it.

If I were you, I post it to another method.
#using (Html.BeginForm("Index", "Home", "POST"))
{
<div class="searchField">
<div class="searchbox">
Search: <input type="text" name="Search" />
<input type="submit" value="Submit">
</div>
</div>
}
#Html.Partial("PartialAnalysis", (string)ViewBag.SearchKey)
#Html.Partial("PartialSlag", (string)ViewBag.SearchKey)
//In Home Controller
[HttpPost]
public ActionResult Index(string Search)
{
ViewBag.SearchKey = Search;
return View();
}

Partial views do not require a controller action. The presence of a controller action will actually make it into a view.
In your #Html.Partial call you want to pass a view model for the view to consume. This is where you'd want to put the data for your grid, searched by whatever keywords, sorted, prepped and ready to render.
This can either be an entirely different view model you've created that is dedicated to supporting your partial view, exposed as a property in the parent page's view model, or simply an IEnumerable property in the parent page's view model that has the data (I prefer the first approach btw; it's heavier code-wise but preserves encapsulation better).
To wrap it all up, your controller looks like:
public class HomeController : Controller
{
public ActionResult Index(string search)
{
return View(new IndexViewModel(search));
}
}
Your view model looks like:
public class IndexViewModel
{
private string _search;
public IndexViewModel(string search)
{
_search = search;
}
public AnalysisViewModel AnalysisViewModel
{
get
{
return new AnalysisViewModel(_search);
}
}
public SlagViewModel SlagViewModel
{
get
{
return new SlagViewModel(_search);
}
}
}
and your view for showing the partials looks like
#Html.Partial("PartialAnalysis", Model.AnalysisViewModel)
#Html.Partial("PartialSlag", Model.SlagViewModel)

I needed to change my partial view calls in my view to:
#if(ViewBag.SearchKey != null)
{
<div>
#Html.Action("PartialChemAnalysis", "Home", (string)ViewBag.SearchKey)
</div>
<div>
#Html.Action("PartialSlagView", "Home", (string)ViewBag.SearchKey)
</div>
}

Related

Why asp-for input tag helper always use form data instead of the viewmodel?

My goal is, when a form is submitted, to be able to display the form again, but with a modified model, where I replace some values.
Take this simplified code for example:
public class IndexController : Controller
{
[HttpGet("")]
public IActionResult Index()
{
return View(new IndexViewModel() { Origin = "GET" });
}
[HttpPost("")]
public IActionResult Index(IndexViewModel viewModel)
{
viewModel.Origin = "POST";
viewModel.Name = "Fixed Name"; // I want to force this value
return View(viewModel);
}
}
public class IndexViewModel
{
public string Name { get; set; }
public string Origin { get; set; }
}
The following view:
#model IndexViewModel
<html>
<body>
<form method="post">
Name : <input asp-for="Name" /><br />
Origin : #Model.Origin
<br />
<button type="submit">Submit</button>
</form>
</body>
</html>
When I submit the form, the method goes through the POST method, but the view HTML only use the original form values.
The value "Fixed Name" is ignored and never used when rendering the view.
I suppose the asp-for tag helper always give higher priority to FormCollection values. Is there a way to force the use of the Model value ?
I cant answer why this happens, possibly someone more knowledgable can, but I've had to use the Post-Redirect-Get pattern:
[HttpPost("")]
public IActionResult Index(IndexViewModel viewModel)
{
viewModel.Origin = "POST";
// persist model or use TempData
return RedirectToAction("AfterPost");
}
public IActionResult AfterPost()
{
// get model or retrieve from TempData
viewModel.Name = "Fixed Name"; // I want to force this value
return View(viewModel);
}

Passing hidden object from view to controller

I have a controller sending a view model consisting of a list and an object client to a view.
The view will show the list in a grid but hide the object client.
Here is the view:
#model .Business.BusinessModels.MatchesClientViewModel
#{
ViewBag.Title = "SaveClient";
}
<h2>SaveClient</h2>
<h3>
The info captured matches #Model.ClientMatches.Count()
</h3>
#using (Html.BeginForm("SaveClient", "Client", FormMethod.Post))
{
#Html.AntiForgeryToken()
WebGrid grid = new WebGrid(Model.ClientMatches);
#grid.GetHtml(columns: new[]
{
grid.Column("Name"),
grid.Column("Surname"),
grid.Column("Email"),
})
#Html.Hidden("client", Model.client)
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
}
My action which submit button hits is:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SaveClient(MatchesClientViewModel matchesClientViewModel)
{
*some actions*
return View();
}
However the view model sent to controller from view is null. Any idea how to properly pass the hidden part of the view model to the controller?
If you want to pass an entire object as hidden you will have to add hidden fields for every attribute of the class like this:
Let's say the model Client is something like this
public class Client
{
public string Id { get; set; }
public string SomeAttribute { get; set; }
\\ ......
}
In order to pass your values to your Action you should add to your form every property as a hidden field like this
#Html.HiddenFor(m => m.client.Id, Model.client.Id)
#Html.HiddenFor(m => m.client.Someattribute, Model.client.Someattribute)
One other way to go would be to change your model to something like this:
public class MatchesClientViewModel
{
public List<ClientMatch> ClientMatches { get; set; }
public string clientId { get; set; }
\\ .....
}
and pass your clientId only to your view and back to the controller like this
#Html.HiddenFor(m => m.clientId., Model.clientId)
Or If you do not want to change your ViewModel just add a hidden field like you did for your object for the client id and pass it as an extra parameter to the controller
#Html.HiddenFor('clientId', Model.client.Id)
and make your action like this
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SaveClient(MatchesClientViewModel matchesClientViewModel, string clientId)
{
*some actions*
return View();
}

ASP #Html.HiddenFor not posting data

So I've got a simple model called BaseModel that has properties all models need. Like for example my Provider class.
public Provider Provider { get; set; }
And I have a SearchModel that derives from BaseModel. It just has an extra string and list.
Now in my html file I have this:
In the top I declared my model:
#model SearchModel
And in my page, I have this form.
#using (Html.BeginForm("Search", "Home", FormMethod.Post))
{
#Html.EditorFor(model => model.SearchText)
#Html.HiddenFor(model => model.Provider)
<button id="BtnSearch" type="submit">Search</button>
}
And finally this is my controller:
public ActionResult Search(SearchModel model)
{
Session["Provider"] = model.Provider;
if (!string.IsNullOrEmpty(model.SearchText)) model.Search();
return View(model);
}
Only what seems to happen is, Provider is null when it reaches my POST action. The weird thing is, it worked in the past and I don't recall changing anything.

Asp.net share values across partial views

I am having trouble with sharing the values of my partial views across the views.
My main view:
<ul class="nav nav-tabs" style="margin-bottom: 5%;">
<li id="first" role="presentation" class="active"><a>Anschrift</a></li>
<li id="second" role="presentation"><a>Kunden Daten</a></li>
<li id="third" role="presentation"><a>Preis / Zahlung</a></li>
</ul>
#model CustomerViewModel
<div id="inhalt">
#Html.Partial("_General", Model)
</div>
The script for my view:
$("#first").click(function () {
$("#inhalt").load('#Url.Action("General", "Home")');
});
$("#second").click(function () {
$("#inhalt").load('#Url.Action("Data", "Home")');
});
#first and #second are buttons.
All views are nested inside a controller and my goal is to share the models across the partial views.
My controller:
public ActionResult Customer()
{
return View();
}
public ActionResult General(CustomerViewModel model)
{
return PartialView("~/Views/Home/_General.cshtml");
}
public ActionResult Data(CustomerViewModel model)
{
return PartialView("~/Views/Home/_Data.cshtml");
}
Customer is the main view in which the partial views are getting rendered.
A snippet from my partial view:
#model CustomerViewModel
<h1>General Partial View</h1>
#Html.TextBoxFor(model => model.Name1, new { #class = "text", placeholder = "Name 1", id = "Name1" })
Edit:
I tried the following code in order to share the model with the different views:
$("#inhalt").load('#Url.Action("Data", "Home", model)');
But this didn't seem to work because when I am debugging the controller everything in the model is null.
Explanation:
I press a list element which has an id (#first, #second..). The I want to replace the div with the id of #inhalt with my partial views. In order to do that I am using the javascript to replace the div with the partials, which all works fine. But I am not able to pass my model to the views. How do I achieve this?
Since you are passing in your model on the route (URI) you'll need to use Route Values here.
<img src="#Url.Action("DisplayData", "Home", Model.RouteValues)" alt="Image" />
As was shown in Binding the Model variable to an Action Method in ASP.NET MVC3
public class MyViewModel
{
public string Name { get; set; }
public string Surname { get; set; }
public bool IsPeriod { get; set; }
public RouteValueDictionary RouteValues
{
get
{
var rvd = new RouteValueDictionary();
rvd["name"] = Name;
rvd["surname"] = Surname;
rvd["isPeriod"] = IsPeriod;
return rvd;
}
}
}
or call directly using the Route Values
<img src="#Url.Action("DisplayData", "Home", new RouteValueDictionary(Model)" alt="Image" />
Keep in mind that because you are using the URL you can run across limits in length and the entire model may not fit, in that case you'd need to load via POST and not GET.

Passing variables with POST in ASP.NET MVC

I am trying to pass a string variable inside asp.net MVC. I use breakpoints so I see that it does go to the correct method in the controller, but the variables posted are equal to null.
My markup:
#{
ViewBag.Title = "TestForm";
}
<h2>TestForm</h2>
#using (Html.BeginForm()) {
<input type="text" id="testinput" />
<input type="submit" value="TestForm" />
}
My controller:
public ActionResult TestForm()
{
return View();
}
[HttpPost]
public ActionResult TestForm(string testinput)
{
Response.Write("[" + testinput + "]");
return View();
}
I put the breakpoint inside the second TestForm method and testinput is null....
Am I missing something?
Note: I realize that most of the time I will be using the model to pass data around, but I would like to know that I can pass strings as well.
As part of the same question, how do I pass several variables? Would the method in my controller look like this:
[HttpPost]
public ActionResult TestForm(string var1, var2)
{
}
For me it looks like that you set the id not the name. I use MVC3 every day, so i dont reproduce your sample. (I am awake for 20 hours programming ;) but still motivated to help ) Please tell me if it dont work. But for me it looks like you have to set the "name" property ... not the id property. Try that ... i am waiting right now to help you if it does not work.
<input type="text" id="testinput" name="testinput" />
On a slightly separate note there is nothing wrong with passing variables like you are, but a more efficient way would be to pass around a strongly typed view model allowing you to take advantage of many aspects of MVC's goodness:
strongly-typed views
MVC Model Binding
Html Helpers
Create a new view model:
public class TestModel
{
public string TestInput { get; set; }
}
Your test controller:
[HttpGet]
public ActionResult TestForm()
{
return View();
}
[HttpPost]
public ActionResult TestForm(FormCollection collection)
{
var model = new TestModel();
TryUpdateModel(model, collection);
Response.Write("[" + model.TestInput + "]");
return View();
}
Your view:
#model <yourproject>.Models.TestModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>TestForm</title>
</head>
<body>
<div>
#using(Html.BeginForm())
{
<div class="editor-label">
#Html.LabelFor(m => m.TestInput)
</div>
<div class="editor-label">
#Html.TextBoxFor(m => m.TestInput)
</div>
<input type="submit" value="Test Form"/>
}
</div>
</body>
</html>

Categories

Resources