Problem is : I do have Index.cshtml as
#{
ViewBag.Title = "Search";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<script src="#Url.Content("../../Scripts/jquery.unobtrusive-ajax.min.js") type="text/javascript"></script>
<h2>Answer's are </h2>
<div id="result">
#Ajax.ActionLink("Search Wiki",
"WikiAns",
new AjaxOptions{
UpdateTargetId = "result",
InsertionMode=InsertionMode.Replace,
HttpMethod="GET",
LoadingElementId="progress"
})
</div>
<div id="progress" style="display: none">
<img src="#Url.Content("../../Content/Images/ajax-loader.gif")" alt="loader" />
</div>
Now i do have partial view model _WikiAns:
#model IEnumerable<Questions.Models.WikiAnsClass>
<h2>Our Links</h2>
<table>
#foreach (var item in Model) {
<tr>
<td>
#item.content
</td>
</tr>
}
</table>
Now using above i want is that...on clicking Search Wiki action link, id="result" get all partial view rendered in it. But its not happening. Instead of its going to a page "localhost:80/Search/WikiAns" and showing the result there. but i want to it to stay at localhost:80/Search and replace its "result" id. but its not working this way.
Here is my action called WikiAns
public ActionResult WikiAns()
{
//Code to follow...
var wikians = //code to follow
return PartialView("_wikiAns", wikians);
}
What's the problem ?
Also how can i implement this Ajax GIF loader...i mean showing it while action gets executed. ?
Please suggest
Thanks
#Pbirkoff may be right about this but you can go through my post of very easy to implement demo of your scenario and build it up from there.
http://mazharkaunain.blogspot.com/2011/05/aspnet-mvc-razor-render-partial-view.html
http://mazharkaunain.blogspot.com/2011/04/aspnet-mvc-render-partial-view-using.html
You need to include Microsoft Ajax scripts at your page or layout.
Related
Overview:
I am essentially building a single page application. Three inputs and two tables that load based on the inputs' data.
Each table is set to a tab and each tab has a button to load their respective table's data. One table is set in a partial view. I'm trying this out to see if it works so I can set both of the tables to a partial view.
Problem:
The partialview is loading the table into a new window when I click the submit button.
Example:
So, upon loading the web application, for example, 'http://localhost:30000/CommissionDatas/' the Index page loads the page and the empty tables just fine.
I am using a ViewModel because each table uses a different model and I will get an error about the Partial view table having a different data model.
Once I click the button "gpmbutton", for the partial view table, the buttion uses the 'formmethod' attribute to call actionresult method '_TrueUp' and it will retrieve the data and return the data model to the partial view. But, the partial view's table and it's data ends up posting the to 'http://localhost:30000/CommissionDatas/_TrueUp', which is a completely new page.
I have already tried changing the actionresult method type to PartialViewResult and changing the return type from 'PartialView()' to a 'View' in the controller and that still did not work. I've also tried using #Partial in the index page as well as #RenderPartial for the partial view and I get the same result.
Also, both the 'Index' and the '_TrueUp' PartialView page are in the same folder under 'CommissionDatas' in the views folder.
Please HELP!
P.S. I removed the code that is not essential to the problem as the data is sensitive.
Index.cshtml
-------------------------------------------------------------
#model CommissionReport.Models.ViewModels.CommissionViewModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<input type="submit" ID="commissionbutton"
formaction="ReturnCommissionData"
formmethod="post"
/>
#if (Model != null)
{
<table id="mainTable" class="ui striped selectable table">
<thead>
<tr>
</tr>
</thead>
<tbody>
#foreach (var item in Model.CommissionData)
{
<tr>
</tr>
}
</tbody>
</table>
}
<input type="submit" class="btn btn-primary" ID="gpmbutton"
formaction="_TrueUp" formmethod="post"
/>
<div>
#if (Model != null)
{
Html.RenderPartial("_TrueUp");
}
</div>
</body>
</html>
This is the Partial View
_TrueUp.cshtml
----------------------------------------------------------------------------
#model CommissionReport.Models.ViewModels.CommissionViewModel
#{
Layout = null;
var trueupmodel = Model.TrueUp;
}
#if (Model != null)
{
<table id="mainTable" class="ui striped selectable table">
<thead>
<tr>
</tr>
</thead>
<tbody>
#foreach (var item in Model.TrueUp)
{
<tr>
</tr>
}
</tbody>
</table>
}
This is the Controller.
private CommissionViewModel vm = new CommissionViewModel();
[HttpPost]
public ActionResult ReturnCommissionData(FormReturn form)
{
//Code to return data here
vm.CommissionData = db.CommissionDatas.ToList();
return View("Index", vm);
}
<HttpPost>
public ActionResult _TrueUp(FormReturn form)
{
//Code For Data to be returned here
vm.TrueUp = model;
return PartialView("_TrueUp", vm);
}
Please try #Html.Action("yourAction", "yourController") instead of #Html.RenderPartial("_TrueUp").
For further information visit:
How can I use Html.Action?
MSDN
EDIT:
Use: #Html.Partial("partialViewName", partialViewModel) partialViewModel is optional.
In your case: #Html.Partial("_TrueUp").
I am using ASP.NET MVC, I have finished my project and I copied the .sln solution files to the server.
When I run it on the server, everything ok, but there is showing exceptions for the Popup forms.
I have this controller
-- The Get method
public ActionResult Remove(int id)
{
Person Person_to_remove = new Person() { Person_Id = id };
return View(Person);
}
-- The Post method
[ActionName("Remove"), HttpPost]
public ActionResult Remove_post(int id)
{
DB.Remove(id);
return RedirectToAction("Index");
}
And these views:
Index View
<table>
<tr>
<th>Name</th>
<th>Remove?</th>
</tr>
#foreach (var row in Model)
{
<tr>
<td>#row.Name</td>
<td>
Remove
<script type="text/javascript">
function Open() {
window.open('#Url.Action("Remove", new { id = row.Id })', 'popup', 'width=450,height=250');
return false;
}
</script>
</td>
</tr>
}
</table>
Remove View (As a popup window)
#using (Html.BeginForm())
{
<main>
<div>
<h3>Confirm removing:</h3>
<h1>#Model.Name</h1>
<br />
<div class="row">
<div>
<button type="submit" onclick="updateParent();">Confirm</button>
<a onclick="window.close()">Cancel</a>
</div>
</div>
</div>
</main>
}
The Index view use a default "Layout" layout and the Remove view use a "Popup" layout on the shared folder
This is the updateParent() script running on the "Popup" layout
<script type="text/javascript">
function updateParent() {
window.opener.location.reload();
window.close();
}
</script>
On my computer the app works fine, but when running on the server the popup views won't post the form, they just close without updating the data.
But when using the same URL from the Popup window into a new tab, it works. but is not desired behaviour.
I don't know what is going on, i only changed the IP in the connection string.
The problem was that the form was closing before submitting. Thanks to derloopkat for the tip.
To solve this I change Razor #Html.BeginForm() to name the form "PopUp".
Html.BeginForm(null, null, FormMethod.Post, new { name = "PopUp", id = "PopUp" })
then modify the updateParent method, to submit the form.
<script type="text/javascript">
function updateParent() {
document.forms["PopUp"].submit(); <-- Added
window.opener.location.reload();
window.close();
}
</script>
Don't know if it's the best way, but it works.
I'm very new to MVC and I'm trying to figure out if there is a better way to do this. I have a textbox for the user to put in their search, then based on that search I am displaying some results below said search box. I am trying to avoid having so much code logic in my view and would like to know if there is a better way of handling this. Here is my existing code, where based on what the value of "Model.Results" is it will return one of 3 partial views or a button if the rest of my logic passes:
#section CustomerPrefixInfo
{
#if (Model.Results == PrefixSearch.SearchResults.CustomerFound)
{
#Html.Partial("_CustomerPrefixInfo")
}
#if (Model.Results == PrefixSearch.SearchResults.PrefixResultsFound)
{
#Html.Partial("_PrefixResults")
}
#if (Model.Results == PrefixSearch.SearchResults.AnimalsFound)
{
#Html.Partial("_AnimalSearchResults")
}
#if (Model.Results == PrefixSearch.SearchResults.ValidNewPrefix)
{
using (Html.BeginForm("Index", "PrefixManagement", new { prefix = Model.AnimalPrefix.Prefix, dbPrefix = Model.AnimalPrefix.DbPrefix }))
{
<fieldset>
<input id="btnReservePrefix" type="submit" value="Reserve Prefix" />
</fieldset>
}
}
}
I would like to put this inside a controller so that it just returns the view that is to be displayed, then just display that view on the page. Aftering doing some rearch I thought using Ajax.BeginForm with the InsertionMode set to InsertAfter would do the trick:
#using (Ajax.BeginForm("GenericSearch", "Home", FormMethod.Post, new AjaxOptions { InsertionMode = InsertionMode.InsertAfter, UpdateTargetId = "searchResults" }))
{
<fieldset>
<input id="btnPrefixSearch" type="submit" value="Prefix Search/Validate"/>
#Html.EditorFor(model => model.Input)
</fieldset>
<div id="searchResults">
</div>
}
My GenericSearch Action then uses a switch to decide which partial view to return:
public ActionResult GenericSearch(PrefixSearch prefixSearch)
{
//some database logic here to get the results
switch (prefixSearch.Results)
{
case PrefixSearch.SearchResults.CustomerFound:
return PartialView("_CustomerPrefixInfo", prefixSearch);
case PrefixSearch.SearchResults.PrefixResultsFound:
return PartialView("_PrefixResults", prefixSearch);
case PrefixSearch.SearchResults.AnimalsFound:
return PartialView("_AnimalSearchResults", prefixSearch);
default:
return null;
}
}
But when I tried this it puts the partial view on a new page.
here is one of my partial views (they are all 3 mostly identical to this)
#model MVC_Test_Project.Models.PrefixSearch
#{
ViewBag.Title = "PrefixResults";
}
#{
Layout = null;
}
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.PrefixResults[0].Prefix)
</th>
<th>
#Html.DisplayNameFor(model => model.PrefixResults[0].CustomerCount)
</th>
<th>
#Html.DisplayNameFor(model => model.PrefixResults[0].Link)
</th>
</tr>
#foreach (var item in Model.PrefixResults)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Prefix)
</td>
<td>
#Html.DisplayFor(modelItem => item.CustomerCount)
</td>
<td>
edit
</td>
</tr>
}
</table>
Any help would be appreciated!
Edit Just a helpful hint in case anybody makes the same stupid mistake I did, make sure your bundles are called before your scripts.
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/bootstrap")
<script src="/Scripts/jquery.unobtrusive-ajax.js"></script>
<script src="/Scripts/jquery.unobtrusive-ajax.min.js"></script>
I had added in those last 2 lines when it was mentioned to use those, but they were above my bundles....and thus the ajax didn't work because of it. Thanks for everybodies help, all is well now!
--Joseph
I would like to put this inside a controller so that it just returns the view
Seems pretty straight forward:
ViewModel:
public class MyModel
{
public string PageToRender { get; set; }
}
Controller Action
public ActionResult DoLogic()
{
//var Results = ?? as The ENum
switch(Results)
{
PrefixSearch.SearchResults.CustomerFound:
model.PageToRender = "_CustomerPrefixInfo";
// etc etc
}
return View(model);
}
View:
#{if (!string.IsNullOrEmpty(model.PageToRender))
Html.RenderPartial(model.PageToRender);}
Although I would probably decorate the Enum:
public enum SearchResults
{
[Display(Name="_CustomerPrefixInfo")]
CustomerFound
}
And then there is no switch statement, you just grab the enum value display attribute's name value.
Make sure you are including jQuery and jquery.unobtrusive-ajax.js (or jquery.unobtrusive-ajax.min.js) at the top of your page you want to perform the Ajax on.
Like this:
<script src="~/scripts/jquery-1.x.x.js" />
<script src="~/scripts/jquery.unobtrusive-ajax.js" />
...
The rest of your page down here
...
This allows the Partial's postback to be rendered in-page, rather than re-directing you each time.
If you haven't got the jQuery files, or are unsure how to include them; have a read here: http://www.c-sharpcorner.com/UploadFile/4fcb5a/update-a-div-and-partial-view-using-ajax-beginform-on-form-s/ - it's very useful.
Ensure that Unobtrusive JS is enabled, in your web.config file, also. They look like this in the <appsettings> node:
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
If you are using validation - which I doubt you are for a search; but stay with me - you may also want to include jquery.validate.js and jquery.validate.unobtrusive.js, too. This can allow client-side validation (where possible) making the UX a lot smoother.
NOTE: There are other ways of doing the Ajax request; such as creating it in your own JS script - this example is the easiest using an already-available and much-loved library :)
Hope this helps!
EDIT
The switch on which Partial view to return can then be done solely from inside your Controller. You can remove the logic from within the page view.
The Ajax will then take care of replacing the content of the div's ID you gave to the Ajax.BeginForm helper.
You could either replace the search form entirely - by using its ID, or, better still - place an empty <div> container within the page, ready to display the results in:
<div id="searchResults"></div>
The Ajax will then return the Partial view and put the content inside your searchResults div.
EDIT 2
I noticed in your Ajax.BeginForm's AjaxOptions object you are missing HttpMethod = "POST".
The AjaxOptions should look something like this:
new AjaxOptions {
HttpMethod = "POST",
UpdateTargetId = "searchResults",
InsertionMode = InsertionMode.Replace
}
I have a new MVC4 project.
In my _Layout.cshtml I have the following:
<div class="container maincontent">
<div class="row">
<div class="span2 hidden-phone">
#*
In here is a RenderSection featured. This is declared in a section tag in Views\Home\Index.cshtml.
If this is static text for the whole site, don't render a section, just add it in.
You should also be able to use #Html.Partial("_LoginPartial") for example.
This _LoginPartial will need to be a cshtml in the Shared Views folder.
*#
#{ Html.RenderPartial("_NewsFeed"); }
</div>
<div class="span10">
#RenderBody()
</div>
</div>
</div>
My partial view is
<div class="row newsfeed">
NEWS FEED
#foreach (var item in ViewData["newsfeed"] as IEnumerable<NewsItem>)
{
<div class="span2 newsfeeditem">
<h3>#item.NewsTitle</h3>
<p>#item.NewsContent</p>
#Html.ActionLink("More", "NewsItem", "News", new {id=#item.Id}, null)
</div>
}
Is there a way I can make the partial view make the data call. Currently I have to do the following in my controller for every action:
ViewData["newsfeed"] = _db.NewsItems.OrderByDescending(u => u.DateAdded).Where(u => u.IsLive == true).Take(4);
return View(ViewData);
I come unstuck where I already pass in a model to a view as I cannot then pass this into it as well.
I know I am doing something wrong, just not sure what or where.
I just want to be able to make a render call in my _layout and then the partial view to know to collect the data and then render itself. Or have I got the wrong end of the stick? I suppose I am trying to use it like an ascx...
You should switch from using a RenderPartial to a RenderAction. This allows you to go through the pipeline again and produce an ActionResult just like a partial, but with server side code. For example:
#Html.RenderAction("Index", "NewsFeed");
Then you make a NewsFeedController and provide an Index action method:
public class NewsFeedController : Controller
{
public ActionResult Index()
{
var modelData = _db.NewsItems.OrderByDescending(...);
// Hook up or initialize _db here however you normally are doing it
return PartialView(modelData);
}
}
Then you simply have your CSHTML like a normal view in your Views/NewsFeed/Index.cshtml location.
I am creating a page with a search property. The user will enter a number in the search field and hit the submit button. I need to be able to call a controller method in order to run the search code.
For now I am just trying to hit a partial page to just get some functionality in there. Below is the code I have so far. As of now nothing happens when I click the button. I hear Ajax was something to use so I have been playing with that a little. I am still learning the framework so bear with me.
<div class="span6 roundedCorners">
<div class="row-fluid Title">
<div class="span6">
Search Area
</div>
</div>
<div class="row-fluid individual">
<div class="row-fluid">
<div class="span4"><span class="pull-right fieldDescription">Number</span></div>
<div class="span8"><input /></div>
</div>
<div class="row">
<div class="span12" id="adminSubmitButton">
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "_adminDetails" }))
{
<button type="submit" class="btn btn-inverse">Submit</button>
}
</div>
</div>
</div>
Your form is empty, it only has a submit button. You will need to move your search button inside the form. Something like this:
Model
public class SearchModel
{
[Required]
public string Query { get; set; }
}
View
#model SearchModel
...
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "_adminDetails" }))
{
#Html.EditorFor(m => m.Query)
#Html.ValidationMessageFor(m => m.Query)
<button type="submit" class="btn btn-inverse">Submit</button>
}
<div id="_adminDetails"></di>
Note: Make sure you have an element with id _adminDetails
Your controller will have to take the model and perform the search. Example:
Controller
[HttpPost]
public ActionResult Index(SearchModel model)
{
//do something with your model (perform search)
return View(results);
}
Alright, I have it partially working now. When i click the button I am able to call the controller method using:
function adminButton()
{
$("#adminDetails").load("#Url.Action("ControllerMethod", "ControllerName")");
}
The #Url.Action helper allows me to call the method which returns a partial view. This is a step in the right direction. But from what I am reading I should be able to use the following Url helper instead of the #Url.Action:
"#Url("ControllerMethod", "ControllerName")/" + submitButton.Value
I have tried some variations and I am still doing some reading to figure out a solution. Is there a helper that would let me do this?
Thanks for the help guys. I did end up getting my problem solved friday evening. Basically what I did was load the partial page when the button was clicked through the help of JS/jQuery and the Razor #Url.Action() to call the controller method that returns a PartialView:
<script type="text/javascript">
function adminButton()
{
var link = "#Url.Action("ControllerMethod", "ControllerClass", new {
number = -1})";
var num = parseInt($("#number").val());
link = link.replace(-1, num);
$("#details").load(link);
}
</script>