scripts doesn't executed after partial rendering in mvc, why? - c#

I used mvc 4.0 to develop my web application, I have created a pager and data-list it works fine, I implement it by some jquery code and I define $.get jquery method to get a partial view as new page like this :
$.get("http://localhost:13824/bid/index?page=8&script=1", function(data) {
$Element.html(data);
}
on the other side in control I have Action method like following :
public ActionResult Index(string provinceNo="21", int page=1, string script="0"){
if(script=="1") { return PartialView("mypartialwebusercontrol",model); }
else // do something else;
}
in the web user control I have some items it loads all items and my pager works very nice but there is a problem I have link in each item that is for opening a popup window when I click on pager it calls $.get method. all click events and scripts wont be rise again.
my web user control is like this :
<% control language="c#" inherits="system.web.mvc.viewusercontrol<model>" %>
<% foreach(var item in model) { %>
<div id="card1">
<a class="linkbutton"> item.text1 </a>
</div>
<% } %>
all of the click script will be stop after $.get method calling.

Still not sure what you mean by 'in constructor', but I can see two possible causes of the problem:
One, you are running the bind before you load the html and consequently the linkButtons aren't bound. Solution is to run the bind after loading, or better, use .delegate on the container you are loading into.
Two, when the browser is running the $.get method or any javascript after that, it is hitting an error and stopping executing any more scripts.
If its neither of these, you'll need to give a full listing of your Javascript or a link to a page where me or someone else can see exactly what's going on

Related

Invalid ViewState when using jQuery tabs

I have a fairly simple page with a set of jQuery tabs, the content of some is called via ajax. I also have a search box in the masterpage in my header.
When I open the tabbed page the search box works fine. However once I have clicked on one of the ajax tabs the search box fails to work with an "Invalid Viewstate" yellow screen of death.
I believe this is because the ajax page is replacing the __VIEWSTATE hidden input with its own.
How can I stop this behaviour?
UPDATE: I have noticed that the YSOD only appears in IE and Chrome, Firefox doesn't seem to have the same issue. Although how the browser influences the ViewState, I'm not sure.
UPDATE: I've put a cut down version of the site that shows the issue here: http://dropbox.com/s/7wqgjqqdorgp958/stackoverflow.zip
The reason of such behavior is that you getting content of the ajaxTab.aspx page asynchronously and paste it into another aspx page. So you getting two instances of hidden fields with __VIEWSTATE name and when page posted back to server theirs values are mixing (might depends on how browser process multiple controls with same name on submit). To resolve this you can put second tab's content into a frame:
<div id="tabs">
<ul>
<li>Default Tab</li>
<li>ajax Content</li>
</ul>
<div id="tabs-1">
<p>
To replicate the error:
<ul>
<li>First use the search box top right to search to prove that code is ok</li>
<li>Then click the second ajax tab, and search again.</li>
<li>N.B. Chrome / IE give a state error, Firefox does not</li>
</ul>
</p>
</div>
<iframe id="tabs-2" src="ajaxTab.aspx" style="width:100%;" ></iframe>
</div>
Also, I'm not sure but this seems like error in the Web_UserControls_search control. In my opinion, NavBarSearchItemNoSearchItem_OnClick method must be refactored as below:
protected void NavBarSearchItemNoSearchItem_OnClick(object sender, EventArgs e)
{
var searchFieldTbx = NavBarSearchItemNo;
var navBarSearchCatHiddenField = NavBarSearchCatHiddenField;
var term = searchFieldTbx != null ? searchFieldTbx.Text : "";
if (term.Length > 0) //There is actually something in the input box we can work with
{
//Response.Redirect(Url.GetUrl("SearchResults", term));
Response.Redirect(ResolveClientUrl("~/Web/SearchResults.aspx?term=" + term + "&cat=" + navBarSearchCatHiddenField.Value));
}
}
Draw attention that we resolving client url when redirecting to search results page and instead of navBarSearchCatHiddenField use navBarSearchCatHiddenField.Value as cat parameter.
I guess that you use AJAX to fill the content of the tab. So in this case, content of your tab will be replaced by the new one from ajax and certainly _VIEWSTATE will be replaced. At server, do you use data from ViewState? In the "static tabs", you should prevent them auto reload by using cache:true
Your issue is that with your ajax call you bring in a complete ASPX page. Including the Form tag and its Viewstate. If you remove the Form tag from ajaxTab.aspx you will see everything works fine. asp.net does not know how to handle two Form tags in one page. Same goes for hidden Viewstate fields. You cannot bring in a full aspx page via ajax. Just bring in the content Div you want to display and you`ll be good to go.

MVC partial views for elements that are similar, but are not exactly the same

I am currently working on converting an existing webforms application to MVC and am not sure how to design one of the pages. The existing page is 2500 lines of code, and is responsible for displaying several different views of the same information. The following example is just a small piece of this page (a toolbar), but I'm not sure what the best approach is to avoid duplicating code.
Administrator view toolbar:
Save, PDF, Print, Spell Check, Administrative Documents, Employee View Toggle
Manager view of toolbar:
Save, PDF, Print, Spell Check, Employee View Toggle
Employee view of toolbar:
Save, PDF, Print, Spell Check
I have split the application into three different views. They use the same partial views to render the content of the page, but currently each view has it's own copy of the toolbar. So the HTML elements for Save, PDF, Print and Spell Check are duplicated in each of the views. It would be ideal to have a partial view to render the toolbar, but in order to do that I would need to put some sort of logic in the view to determine if it should show the Employee View Toggle link or the Administrative Documents.
I have also ran into similar problems while developing other new pages. Initially the requirements for different pages have the same element on them that we split into a partial view. After testing and adding more functionality, eventually the partial view needs to be slightly different on each of the pages. Usually it's just the visibility of the certain controls, but eventually the partial views end up having a bunch of logic in them to check several things to determine if something should be shown.
What is the best approach for dealing with slightly different views where most of the elements are the same?
If it's just an issue of permissions showing or hiding different parts of the same control/partial view/whatever, I would say just write one and have some code in it to check permissions and conditionally render or don't render various parts. Something like this:
<%# Control Language="C#" %>
This is the toolbar!!
<div class="fake-css-class">
<%:Html.ActionLink("Save", "Save") %>
<%:Html.ActionLink("PDF", "Pdf") %>
<%:Html.ActionLink("Spell Check", "SpellCheck") %>
<% if (CurrentUser.IsInRole("Admin") { %>
<%: Html.ActionLink("Administrative Documents", "AdminDocs") %>
<%} %>
<% if (CurrentUser.IsInRole("Admin") || CurrentUser.IsInRole("Manager"){
%>
<%: Html.ActionLink("Employee View Toggle", "EmpView") %>
<%} %>
</div>
<br />
<br />
EDIT:
When the logic gets more complicated, add functions to your security code so that you can separate all the logic out into your model/controller and in the view you're making a single function call. For example something like this:
public bool Authorize(string controllerName, string actionName) {
bool authorize = false;
foreach(var permission in this.permissions) {
if (permission.Matches(controllerName, actionName)) {
authorize = permission.Affirmative;
}
}
return authorize;
}
This way you could have the code outside of the view and simply a single line of code in the view. The above code is just taken out of my current project and used as an example, but you can write whatever complicated logic and put it out in the model or controller so your view stays clean and you aren't putting business logic in there.

Manage tabbed content with full support for routing

I'm building an Asp.net mvc 3 application. What I want to do, is a profile page (pretty mutch like the stackoverflow profile page), and the content of this page will be splited in tabs, each tab is represented by an PartialView.
When the user click on the tab X, I want to refresh only the tab area, without refreshing all my page. And in the same time changing my URL adress, so if the user click on the browser refresh button, it refresh the page with the selected tab. Is this possible ?
What I already know, is how to get data using AJAX, and replace the content of my view. I've read this post , I found it interesting, but it refresh all the page.
Thanks in advance.
You are on the right track. You will need to use both ajax to get the html to render without refreshing the page, as well as use push state to update the URL to include the current tab.
You could do these things as separate operations, but I would suggest using PJAX. With PJAX you will need a little additional logic in your server to decide whether to return the full html page with the layout, or just return the partial (a PJAX request).
Here is our Foo controller. Index has a default selected tab of "Bar". The Bar and Baz actions return the Index view, but with different tabs being the selected tab. If it is a PJAX request, then all we need is the partial view that fills in the tab content.
public class FooController : Controller
{
public ActionResult Index()
{
ViewBag.SelectedTab = "Bar";
return View();
}
public ActionResult Bar()
{
if(Request.Headers["X-PJAX"] != null)
return PartialView();
ViewBag.SelectedTab = "Bar";
return View("Index");
}
public ActionResult Baz()
{
if (Request.Headers["X-PJAX"] != null)
return PartialView();
ViewBag.SelectedTab = "Baz";
return View("Index");
}
}
Inside of the Foo/Index.cshtml we have the Razor code that will determine what partial view to render based on ViewBag.SelectedTab.
#{
ViewBag.Title = "Foo";
}
<h2>Foo</h2>
<ul>
<li><a class="tabs" href="#Url.Action("Bar", "Foo")">Bar</a></li>
<li><a class="tabs" href="#Url.Action("Baz", "Foo")">Baz</a></li>
</ul>
<div id="tab_content">
#if(ViewBag.SelectedTab == "Bar")
{
#Html.Partial("Bar")
}
#if (ViewBag.SelectedTab == "Baz")
{
#Html.Partial("Baz")
}
</div>
#section scripts
{
<script type="text/javascript">
$(function() {
$(".tabs").pjax("#tab_content");
})
</script>
}
The script section at the end is how you wire up PJAX. You are telling it, for all hyperlinks with the tabs class use pjax to dynamically load and render the html resulting from the href into the container with the id tab_content and update the url in the browser to be the url from the href.
Each tab's partial view is fairly simple in this scenario
Bar.cshtml
<p>This is the Bar tab. No pun intended.</p>
Baz.cshtml
<p>This is the baz tab.</p>
This is obviously a very simplified solution. You typically would want to use a presentation model to handle the logic of the view. Also, I have intentionally left out any tab styling to demonstrate that this technique can be used on any type of link. It is not limited to only tabs.
The full source code for this example can be on my GitHub site.
When the user click on the tab X, I want to refresh only the tab area, without refreshing all my page. And in the same time changing my URL adress, so if the user click on the browser refresh button, it refresh the page with the selected tab. Is this possible ?
To accomplish this you need to plug into browser's history API (and it's part of HTML5, and you'll have to use some kind of plugin to get the same thing in browsers that does not support it).
Manning's "HTML5 for .net developers" has pretty good section on that, but it's still in "early access".

ASP.net user control doesn't call a javascript function

I am developing asp.net web application, I have a repeater that call a registered user control, I have in the user control a button that I want to call a javascript function that make Ajax call to do some action on server. this button doesn't call the javascript method, I don't know why? and when I view source I found the javascript function is repeated for every item in the repeater, how to eliminate this repetition specially that I read server items inside the function, and why the function is not called?
Thanks a lot!
sercontrol.ascx
<div id="divBtnEvent" runat="server">
<input type="button" id="btnAddEvent" class="ok-green" onclick="saveEvent();" />
</div>
<script type="text/javascript">
function saveEvent()
{
var eventText = document.getElementById('<%=txtEventDescription.ClientID%>').value;
// make ajax call
}
Problem 1: In view source I found the javascript function is repeated for every item in the repeater.
Solution:
Put your js function on the page on which the user control is being called. You also have to place your js files references on your page not on user control.
Problem 2: You are trying to get control's value as <%=txtEventDescription.ClientID%>.
And I think, this control is on user control.
Solution: Please check your page source code and see that the control's actual clientid is.
If still have issues in calling js function, check firefox's Error consol.
Hope this help.
OP said and when I view source I found the javascript function is repeated for every item in the repeater
to get rid of it put ur javascript as follows
<head runat="server">
//heres goes ur js
</head>
I guess that's ur problem
Replace the saveEvent function definition from user control onto the page where the control is used. All the way as I understand, you have use in this function textbox id from that page.
Actually, if you have place javascript block in user control's markup it will be rendered along with the rest control's markup. To avoid this you may register javascript from the server code and check is that code block is already registered.
By the way, as it is - only the last function definition being taked into attention as it redefined the previous one each time new control instance rendered.

ASP.NET MVC: How to close browser window instead of returning a view?

I have an instance where, not by my own choice, but I have a secondary popup window in the browser.
Upon form submission back to a server-side MVC method, after this method is complete I'd like it to close that browser window that called it.
Is there a way to do this other than to return a view with javascript in the "onReady" that tells it to close?
No, there isn't a way to achieve this from the server without using javascript (or returning a view that will execute this javascript).
Put this in your view:
#if (ViewBag.ShouldClose) {
<script type="text/javascript">
window.close();
</script>
}
Then if you set the ShouldClose property, it'll run that script and should close the window.
// in your controller
ViewBag.ShouldClose = true;
Note: I did this from the editor so you might have to tweak the view syntax to get it to parse right.
I had the same question and the answer of #Michael Kennedy was exactly what I needed! Since I am using MVC 2 I did have to alter the syntax. I'll put it here as a reference for others.
In the view:
<% if ((bool)ViewData["ShouldClose"]) { %>
<script type="text/javascript">
window.close();
</script>
<% } %>
In the controller:
ViewData["ShouldClose"] = true;
Don't forget to set the ViewData in each call to the view otherwise you'll get a NullReference for the cast to bool.

Categories

Resources