How to access the parent of a parent of a partial view's viewmodel? - ajax

In asp.net mvc3, if I have a top view:
#model BuilderVM
#using (Ajax.BeginForm("TaskSelector", ajaxOpts))
{
}
<div id="here"></div>
which gets updated with a partial view in the div id="here" returned from the action TaskSelector after a post from the Ajax form (i.e. public action TaskSelector(BuilderVM m){var vm = new SelectorVM();vm.property=m.property;return PartialView(vm);}. Inside that div, this next partial view is genereated:
#model SelectorVM
#using (Ajax.BeginForm("Choices", ajaxOpts))
{
}
<div id="selected"></div>
From that partial view, the next partial view is then updated inside the div id="selected".
#model ChooserVM
#using (Ajax.BeginForm("Ender", ajaxOpts))
{
}
<div id="ended"></div>
How, from the action "Ender"
public ActionResult Ender (ChooserVM vm)
{
//access BuilderVM.SomeProperty
}
can I access BuilderVM?

Short answer: you don't. There is no access unless the data is stored in the session.

Related

How to get model from Partial View in MVC

I have a main Index view from which I call view called Create, into which I pass type of the widget I want to create as a string.
Index view:
<i class="fa fa-image"></i> Create Image Widget -
<i class="fa fa-file-text"></i> Create Text Widget
Create Action:
public ActionResult Create(string wType)
{
ViewBag.wType = wType;
return View();
}
the type is then passed into view via ViewBag.wType and this is evaluated in the Create View
Create view:
#using (Html.BeginForm())
{
<section class="row">
#{
if (ViewBag.wType == "image")
{
Html.RenderPartial("~/Views/WidgetEditor/_CreateImageWidget.cshtml");
}
else if (ViewBag.wType == "text")
{
Html.RenderPartial("~/Views/WidgetEditor/_CreateTextWidget.cshtml");
}
}
</section>
}
and depending on this, appropriate partial view is loaded.
Partial views have different models so when the form is submitted, I do not know how which model is passed back. The one from _CreateImageWidget or _CreateTextWidget.
If the HttpPost controller look like this
[HttpPost]
public ActionResult Create(DisplayWidgetImageViewModel imageModel, DisplayWidgetTextViewModel textModel)
{
return new ViewResult();
}
I will get populated imageModel if _CreateImageWidget partial is chosen and textMode if _CreateTextWidget partial is chosen.
This is acceptable it the number of widgets types does not change, but this is not the case.
Is there a way to get somehow specific model from a partial view and know/find out which one it is or am I doing this completely wrong way?
You can create multiple forms in single page. You can also use different action methods per partial:
#using (Html.BeginForm("Action", "Controller")) {
Html.RenderPartial("~/Views/WidgetEditor/_CreateImageWidget.cshtml")
}
You all this without having to use Ajax.
I have used this answer to solve my problem: determine-the-model-of-a-partial-view-from-the-controller-within-mvc
there are also several other link with more resources.

mvc4 Razor Ajax Call to show partial view

Am trying to get a partial view to render with an AJAX call. The following ActionResult is in my base controller which is inherited by all other controllers in the solution:
public ActionResult FileManager()
{
return View("_FileManagerPartial");
}
and the folowing code is another partial that sits on the page
#Ajax.ActionLink("File Manager", "FileManager", new AjaxOptions { UpdateTargetId = "dvFilemanagerContainer" });
dvFilemanagerContainer is a div in the layout view and the partial view "_FileManagerPartial.cshtml" is in the shared views folder.
When I click the link for the ajax call, instead of loading the intended partial view it loads a duplicate of the page into the div.
Any ideas?
Edit
PartialView contents its currently just the following
<div id="dvFilemanagerWrapper">
File Manager
</div>
change your controller to
public PartialViewResult FileManager()
{
return PartialView("_FileManagerPartial");
}
In View add this line, so that with partial view, the master layout is not rendered, only partial view is rendered:
#{
Layout = null;
}
<div id="dvFilemanagerWrapper">
File Manager
</div>
Problem was to do with how my RouteConfig was handling the call. Have created a new MapRoute to point it to the right place and is now working. Thanks for help guys.

partial views to get data and then post the results to save in database

I am very new to MVC, let me try to explain my scenario in plain simple English:
I have an strongly typed mvc form/page (Product.cshtml) with a model, say ProductViewModel.
This page has got two search buttons, one to search and bring the items to be added to the Product and other to bring in the location, most probably partial views.
Now, what I want is that these search results work in ajax form without complete post back, and then the results of these searches (items and location) should be posted back using model binding to the form when user clicks on the submit button.
What could be the best way of achieving this functionality?
Immediate responses will be well appreciated.
I thought, its good to share the complete code for clarity:
I have one form(Service1.chtml) that has a partial view to display users(_TestUser a partial view:read only), then another partial view(_PlotServiceRequestData) that should have a field to search the plot and bring back the details lke its owner name and landuser etc.
Then when I click on submit button of the main form, I should be able to read all data(main form) + new data from _PlotServiceRequestData partial view and save all data to database.
I was trying one more option, that is, to use #Ajax.ActionLink on Service1.cshtml to call the _GetPlotDetails method and then store partial view data in TempData, so that it is available to the form when users clicks on "Submit" button of Service1.cshtml, is this a right approach?, if I use ajax.BeginForm inside partial view then the data is posted to the
Service1 controller method which is actually to save the form data and not to update the partialview and in this method even I am not getting model data of the partial view.
Sevice1.cshtml:
#model ViewModels.TestViewModel
#{
ViewBag.Title =
"Service1";
}
#
using (Html.BeginForm())
{
#Html.LabelFor(m => m.Title)
#Html.EditorFor(m => m.Title)
#Html.Partial(
"_TestUser", Model)
<div id="RequestPlotData">
#Html.Partial(
"_PlotServiceRequestData", Model.requestData)
</div>
<button type="submit">Save Form</button>
}
#section Scripts {
}
_PlotServiceRequestData.cshtml:
===============================
#model ViewModels.PlotServicesRequestDataViewModel
<
div id="RequestPlotData">
#
using (Ajax.BeginForm("_GetPlotDetails", "Test", new AjaxOptions { UpdateTargetId = "RequestPlotData", Url = Url.Action("_GetPlotDetails","Test") }))
{
<h1>Request Details</h1>
 
<div>
#Html.LabelFor(m => m.plotAddress)
#Html.EditorFor(m => m.plotAddress)
<input type="submit" name="submit" value="Ajax Post" />
</div>
<div>
#Html.LabelFor(m => m.LandUser)
#Html.EditorFor(m => m.LandUser)
</div>
<div>
#Html.LabelFor(m => m.OwnerName)
#Html.EditorFor(m => m.OwnerName)
</div>
}
</
div>
CONTROLLER:
==========
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Web;
using
System.Web.Mvc;
namespace
TestNameSpace
{
public class TestController : Controller
{
//
// GET: /Test/
public ActionResult Service1()
{
Injazat.AM.mServices.
LocalDBEntities context = new Injazat.AM.mServices.LocalDBEntities();
TestViewModel model =
new TestViewModel() { user = context.Users.First(), Title = "Land Setting Out",
requestData =
new PlotServicesRequestDataViewModel() { ServiceNumber ="122345", TransactionDate="10/10/2033" } };
return View(model);
}
[
HttpPost()]
public ActionResult Service1(TestViewModel model)
{
PlotServicesRequestDataViewModel s = (PlotServicesRequestDataViewModel)TempData[
"Data"];
TestViewModel vm =
new TestViewModel() { user = model.user, requestData = s, Title = model.Title };
return View(vm);
 
}
[
HttpGet()]
//public PartialViewResult _GetPlotDetails(string add)
public PartialViewResult _GetPlotDetails(PlotServicesRequestDataViewModel requestData)
{
//PlotServicesRequestDataViewModel requestData = new PlotServicesRequestDataViewModel() { plotAddress = add};
requestData.OwnerName =
"owner";
requestData.LandUser =
"landuser";
TempData[
"Data"] = requestData;
return PartialView("_PlotServiceRequestData", requestData);
}
}
}
You can probably use the jQuery Form plugin for this. This makes the process of posting the data from your form back to the server very easy. The form would post to an action that would return a partial view that you can then push into your UI.
To make this easier, jQuery form actually has a "target" option where it will automatically update with the server response (ie. the partial view returned from your search action).
View
<form id="searchForm" action="#(Url.Action("Search"))" method="POST">
<input name="query" type="text" /> <!-- order use Html.TextBoxFor() here -->
<input type="submit" />
</form>
<div id="result"><!--result here--></div>
Javascript
$('#searchForm').ajaxForm({
target: '#result'
});
Controller
public ActionResult Search(string query)
{
// Do something with query
var model = GetSearchResults(query);
return Partial("SearchResults", model)
}
This should hopefully help you to get on the right track. jQuery Form is a good plugin and is the main thing you should look into for ajaxifying your form posts back to the server. You might also want to look into using jQuery's $.post and $.ajax functions, but these require slightly more work.

Ajax.BeginForm not updating target div

Controller:
public ActionResult Edit(string temp)
{
ViewBag.Time = DateTime.Now.ToString("hh:mm:ss");
return PartialView("Edit");
}
Partial View:
#using (Ajax.BeginForm("Edit", "Home", new AjaxOptions{UpdateTargetId = "mydiv"}))
{
<input type="submit" value="Save" />
}
Index View (part of contents)
<div id="mydiv">
<span>The Time is: #ViewBag.Time</span>
</div>
#Html.Partial("Edit")
ClientValidationEnabled and UnobtrusiveJavaScriptEnabled are true
jquery.validate.min.js, jquery.validate.unobtrusive.min.js, jquery.unobtrusive-ajax.min.js, MicrosoftMvcAjax.js and MicrosoftAjax.js are added
At first, the time is shown correctly. When the Save button is clicked for the first time, time disappears and Save button is shown twice and then nothing happens except calling the Action on clicking on both buttons.
You have things kind of backwards. Try this:
Controller
public ActionResult Edit(string temp)
{
ViewBag.Time = DateTime.Now.ToString("hh:mm:ss");
return PartialView("Edit");
}
Index View
#using (Ajax.BeginForm("Edit", "Home", new AjaxOptions{UpdateTargetId = "mydiv"}))
{
<input type="submit" value="Save" />
}
#Html.Action("Edit")
Partial View (Edit)
<div id="mydiv">
<span>The Time is: #ViewBag.Time</span>
</div>
The ViewBag is only accessable at runtime (when the page initially loads) so this means if you fetch data via ajax, the viewbag in the controller action is only accessable to the partial view of that controller action (and not index.cshtml which called the action via ajax). In short (tl;dr) to be able to use the viewbag which you set in Edit action, you need to use it in the returning partialview. (and not anywhere else, because the content isnt re-rendered by the razor engine)
I set things up like so.
Very simple, but I noticed the person posting the
question and the answer had no insertion mode so I posted this lame bit of code :)
{
HttpMethod = "post",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "the div youwant to update / replace"
}

MVC3 is it possible to serve a view section from a controller action?

Suppose I have index.cshtml
#{
ViewBag.Title = "Index";
}
#model SomeModel
#section JS{
content1
content2
content3
}
<div> View Content </div>
Is there any way I could have a controller action that would serve ONLY the section JS for a request for index.js?
Such that navigating to http://somesite/index.js would return
content1
content2
content3
Edit: Some further thoughts on this. My goal would be along the lines say creating a layout page that requires a JS section programmatically, and then composing the View to that layout page and then returning the results of this.
Psuedo code example:
var layout = new LayoutPage();
layout.DefineSection("JS", required: true);
layout.Compose(View("index"))
return layout;
I'm not set on achieving that with what I described but I feel that might offer some more insight on what I'd like to achieve.
You can do something like this (but you'd have to write your own controller action to do it properly)
Index.cshml
#model MvcApplication1.Models.TestModel
#{
ViewBag.Title = "Home Page";
}
<h2>#ViewBag.Message</h2>
<p>
To learn more about ASP.NET MVC visit http://asp.net/mvc.
</p>
#section JS {
blahblahblah
}
JSLayout:
#RenderSection("JS")
Your controller Action
public ActionResult Index() {
return View("Index", "_JSLayout", yourModel);
}
This will output only the JS section. If you want to do it programatically then it will take a bit.
The only way to do it would be to make the content of that section into a partial view, and return the partial view from the controller action.

Resources