how can i render multiple different actions in one call to a speccific controller?
Html.RenderAction() / Html.Action() only handles one controller&action.
But what if i want in one call to render different views on the screen?
thanks in advance,
Sagiv
EDIT:
Hi again.
I'm not sure you understood my question.
this is the cshtml:
<div id="menu">#using (Ajax.ActionLink("click me", "SomeAction","SomeController", new AjaxOptions() { HttpMethod = "POST", OnSuccess = "showMsg", OnFailure = "showError" }))</div>
<div id="div1">bla bla content</div>
....
<div id="div2">bla bla content</div>
and this is the controller:
public class SomeController : Controller
{
public ActionResult SomeAction()
{
return View("somethingfordiv1", ModelForDiv1);
return View("somethingfordiv2", ModelForDiv2); //i want also return another view here
}
}
in this ajax call on the controller, i want to return 2 different views for 2 different divs.
thanks again :)
Here's one way you could proceed. You could aggregate the two view models into a unique view model and then have the controller action return a view containing javascript which will inject the two view results into the different divs.
As always start with the view models:
public class Model1 { }
public class Model2 { }
public class AggregatedModel
{
public Model1 Model1 { get; set; }
public Model2 Model2 { get; set; }
}
Then a controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult SomeAction()
{
var model = new AggregatedModel
{
Model1 = new Model1(),
Model2 = new Model2()
};
Response.ContentType = "text/javascript";
return PartialView(model);
}
}
Then the corresponding ~/Views/Home/Index.cshtml view:
<div id="menu">
#Html.ActionLink("click me", "SomeAction", "Home", new { id = "clickme" })
</div>
<div id="div1">bla bla content</div>
<div id="div2">bla bla content</div>
<script type="text/javascript">
$('#clickme').click(function () {
$.getScript(this.href);
return false;
});
</script>
Next the ~/Views/Home/SomeAction.cshtml view:
#model AggregatedModel
$('#div1').html(#Html.Raw(Json.Encode(Html.Partial("Model1", Model.Model1).ToHtmlString())));
$('#div2').html(#Html.Raw(Json.Encode(Html.Partial("Model2", Model.Model2).ToHtmlString())));
and finally the two ~/Views/Home/Model1.cshtml and ~/Views/Home/Model2.cshtml views:
#model Model1
<span>This is the contents for model1</span>
and:
#model Model2
<span>This is the contents for model2</span>
If you want to render different views on the screen return a model which represents the data for those views, then you can use RenderPartial and pass the part of the model data required to each view.
You can also use viewdata to separately have this available.
Html.RenderAction is also available but simulates another full request
For your ajax request you can return a html chunk from the rendering of a partial view and this can be determined by Request.IsAjaxRequest. Then your javascript can set the result into the document.
This is in your action
if (Request.IsAjaxRequest())
{
return View("PartialViewName", partialModel);
}
return View("NormalView", normalModel);
And the client side example (using jquery)
function hijack(form) {
$("div#SearchResults").html("");
$("div#SearchResults").addClass('loading');
$.ajax({
url: form.action,
type: form.method,
dataType: "html",
data: $(form).serialize(),
success: function(data) {
$("div#SearchResults").removeClass('loading');
$("div#SearchResults").html(data);
}
});
}
Related
I have a model class and a viewmodel class on the similar lines as model class (Code is given below) in a MVC application. There is a view whose model is 'viewmodel' and its a form. The corresponding action method for this form submit button has action parameter as viewmodel class. With this scenario mentioned, model binding works fine.
Now if i change the data type of the Action method from "viewmodel" to "Model" class , Model binding doest not work accurately and correct data is not received on the server side. Below are the model classes -
public class Model
{
public int A { get; set; }
}
public class ViewModel
{
public Model Model { get; set; }
}
View File code is below :
#model ViewModel
#{
ViewBag.Title = "Test";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create</h2>
#using (Html.BeginForm("A", "Customers"))
{
<div class="form-group">
#Html.LabelFor(m => m.Model.A)
#Html.TextBoxFor(m => m.Model.A, new { #class="form-control" })
</div>
<button type="submit" class="btn btn-primary">Save</button>
}
Controller Action Method :
With Correct Model Binding behavior -
public ActionResult A(ViewModel model)
{
return Content("Value of A is " + model.Model.A);
}
If i change the action parameter to Model class , model binding behavior doesnot take place. Below is the code -
public ActionResult A(Model model)
{
return Content("Value of A is " + model.A);
}
Why is it so ?
On the browser side , the form data is as -
Model.A - 1
Why cant this value bind to Model Class A parameter in the second case metioned ?
As your view is bound with ViewModel class (Model binding) so it carries the same model in the post event to server. but in case you wanted to bind with some other model then you have to form new model on the client side like your server side model.
In your case to achieve what you are looking for follow the below code:
<input type="button" value="Save" onclick="SaveData()"/>
<script>
function SaveData() {
$.ajax({
url: "/Home/Save",
dataType: "json",
type: "Post",
data: {
model:{A:10}
},
success:function(data) {
}
});
}
</script>
Please keep the same variable name in client and server side.
public ActionResult Save(Model model)
{
return Content("Value of A is " + model.A);
}
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.
Using jquery.ajax, I am trying to return a view, that has a nested partial view to display a datatable. The initial view is returning, but the datatable is not showing or rendering.
AJAX
$.ajax({
type: "GET",
url: "/Controller/Action,
data: {
custNum: custNum
},
success: function (data) {
$('#DivToRenderResults').html(data);
}
Controller
public ActionResult Action(string custNum)
{
Model ReturnModel = GetData(custNum)
if (Request.IsAjaxRequest())
{
return PartialView(ReturnModel);
}
return View(ReturnModel );
}
Model
public class Model
{
public FirstViewsModel FirstViewsModel {get;set;)
public IEnumerable<DataTableModel> DataTableModel {get;set}
}
I ultimately want to use ajax to dynamically load different tabs that all will have nested datatables in partial views, but I am unable to get this first one to work. Please help, & thank you!
Target View
<div id="DivToRenderResults">
<\div>
// Inside the div
#model Model
<div>
// FirstViewModelInfo
<div>
// This one is not rendering in the return
#Html.Partial("_DataTableView", Model)
</div>
</div>
Problem: We have a Main View and a couple of partial views. Everything uses the same model as the main view. On the submit of Main view, I am trying to render a partial view and trying to pass down the model but only the properties that are getting passed down are the editable fields on the page or view. How can I pass down the other properties?
Current workaround: The partial view needs the other data too to generate a e-mail body but as it is not passed down we are creating hidden fields to pass them down.
Main View
#using (Ajax.BeginForm("CommonSave", "Common", null, new AjaxOptions
{
HttpMethod = "Post",
InsertionMode = InsertionMode.Replace,
//OnSuccess = "submitFormSuccess",
//OnFailure = "submitFormFailure"
}, new { id = "commonForm" }))
{
<div>
<table>
<tr>
<td>
#Html.EditorFor(m => m.Name)
</td>
</tr>
<tr>
<td>
<input type ="submit" name="Common Save" />
</td>
</tr>
</table>
</div>
Controller:
public class CommonController : Controller
{
public ActionResult Index()
{
CommonModel model = new CommonModel()
{
Id = 3,
Name = "Test Name"
};
return View("Common", model);
}
[HttpPost]
public ActionResult CommonSave(CommonModel model)
{
return PartialView("CommonPartial", model);
}
public bool BinderSave(CommonModel model)
{
return true;
}
}
On load of the main view(Common) Index is called.
Upon submitting the Ajaxform on the Main view, the actionmethod CommonSave is called but the model passed to CommonSave only contains the Name and not the Id.
How can we pass that down as well without creating hidden fields or doing anything?
My actual model has a lot of fields which needs to be passed down.
instead of using an ajax form I would use an ajax call and populate the fields on success. Change your button to a button instead of submit
<input type ="button" class="btnSubmit" name="Common Save" />
then in your script tag
$('.btnSubmit').click(function () {
$.ajax({
url: '#Url.Action("CommonSave", "CommonController")',
type: "POST",
data: { Id: $('.Id').val() }
cache: false,
async: true,
success: function (result) {
//put the partial into a div on the form
$(".commonForm").html(result);
//now set the fields on the partial from the model
$('#EmailName').val('#Model.EmailName');
}
});
});
I understand the need for partial views and will tell you how I've solved this however each view should have it's own model, it just should. It's a tenet in the MVVM world:
Anyway, the partials could have a model via a interface. Define your partial view using a interface as it's model. For example:
interface:
public interface IPhone
{
string PhoneNumber ( get; set; }
}
you model:
public class MainModel : IPhone
{
public string Name
{
get { ... }
set { ... }
}
public string PhoneNumber
{
get { ... }
set { ... }
}
}
The point is that as long as the model passed to the main view implements the interface (the interface could also define a property that is another model) that the partial view depends on then all you need to do is pass the model to the partial, you may need to cast the model to the interface but technically you shouldn't have to. Let me know if this helps.
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>
}