Invalid ViewState when using jQuery tabs - c#

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.

Related

Anglesharp HTML parser doesn't seem to be parsing document deep enough to access desired element

So I'm trying to scrape a website using AngleSharp and want to access a particular button that is nested deep in the site. I have logged out the parsed document html with document.DocumentElement.OuterHtml
but can only see so far into the document:
<div class="l-propertySearch-paginationAndSearchFooter" data-test="pagination">
<div data-bind="component: 'pagination'"></div>
</div>
</div>
However, when I inspect the page in the web browser, I can see the additional layers necessary to access the button:
As you can see, the div with the data-bind attribute title "component: 'pagination'" open up further but doesn't display this in the log - this is why, I suspect, I can't retrieve the element.
I've experimented with document.QuerySelectorAll("button" and get back a list of buttons but not the one I'm after - it's like the particular block I want doesn't exist. Any ideas what I'm doing wrong?
As far as I understand that button you are looking for is created with javascript and does not exist in original source code. That is the reason you can't access that button with anglesharp. Right click on website and click View page source (Ctrl + U on chrome) and look for your button there. That is what anglesharp sees not html inside inspect element.

Submit button does not trigger on items added via ajax

I have an mvc view that contains a list of items. Each item is displayed using a partial view. The user can edit, add, and delete items in the list. All of this works.
However, if the user adds an item, the item cannot be edited until the page is refreshed. When the user selects the submit button, the post does not occur. There is no network activity shown in Chrome dev tools - nothing happens.
The output html is the same for items that are included in the initial page load and items added via ajax.
<form action="/booking/UpdateRoomFlow" data-ajax="true" data-ajax-method="POST" data-ajax-success="update_27365547" id="roomflowform_27365547" method="post" novalidate="novalidate"></form>
I noticed that when I inspect element in chrome, the form does not wrap the form fields, but when I look at view source, it does.
I've tried useing Ajax.BeginForm and I've tried writting the html out myself, with the same results either way.
This is the Ajax.BeginForm...
#using (Ajax.BeginForm(
"UpdateRoomFlow",null,
new AjaxOptions
{
HttpMethod = "POST",
OnSuccess = targetfunction
},
new { #id = #formid, #novalidate = "novalidate"}))
{
Any ideas?
EDIT: Something to note - this form is placed inside a tr tag above a td tag, which could cause an issue as that is invalid markup - however, its working in all cases except items added via ajax call.
<script> tags included in an HTML AJAX reponse are stripped, and since Ajax.BeginForm adds script tags to the HTML to enable it's functionality, you essentially end up with a regular old form that does nothing. There's nothing you can do about this, as the browsers strip <script> tags for security reasons. Your only recourse is to stop using Ajax.BeginForm and write your own JS to handle the AJAX submit, which you can then include in the main view or an external file which will not be affected, which is not a bad idea anyways. The Ajax.* family of helpers are awful just for reasons like this.

How can i print a page in asp.net without master page and to change color schemes of the page?

i have made a page in asp.net, i have a costing calculator which has more than 50 fields, dependent on each other, one is the result of previous two and like that, i want my page to be printed in a well manner, and the header of the page which is in master page should not be in print, also the color schemes i want to adjust, let me know the best solution for this which .net provides
Put the content inside <div id="divid">YOUR CONTENT NEEDS TO BE PRINTED</div>
Then call the javascript function on button click which will print the selected area or only html of div. pass the id of div on calling javascript function.
function CallPrint(var strid)
{
var prtContent = document.getElementById(strid);
var WinPrint = window.open('','','letf=10,top=10,width="450",height="250",toolbar=1,scrollbars=1,status=0');
WinPrint.document.write("<html><head><LINK rel=\"stylesheet\" type\"text/css\" href=\"css/print.css\" media=\"print\"><LINK rel=\"stylesheet\" type\"text/css\" href=\"css/print.css\" media=\"screen\"></head><body>");
WinPrint.document.write(prtContent.innerHTML);
WinPrint.document.write("</body></html>");
WinPrint.document.close();
WinPrint.focus();
WinPrint.print();
WinPrint.close();
return false;
}
Call CallPrint('DivGrid');" on onclick() of button or use below: but.Attributes.Add("OnClick", "return CallPrint('DivGrid');");
Nothing to do with .Net and everything to do with a print stylesheet. You can create a stylesheet which will only work for when the page is printed. And you can change everything from what displays to postion to colours.
Use:
<LINK rel="stylesheet" type"text/css" href="print.css" media="print">
Note media="print" means it'll be used for printed pages.
I know that question has been asked a long time ago, however there is no accepted suggestion. So here my approach for friendly print version when using Master page.
Create an empty master page (PrintVersion.Master) to serv as print version. Add what ever you need to be print (like logos) if anything to that master page.
from your content page, add a print link with target blank. Make the href to load the current page. From the href add a querystring so you can capture it from your content page preinit event.
From your content page preinit event detect if the querystring to print exists, then specify the blank master page like: MasterPageFile = "~/Ful/Path/of/your/PrintVersion.Master"
Optional, on the PrintVersion.Master on document.ready call: window.print(); The browser print dialog will automatically open.
You can make a new printable page version, which doesn't include a header. This version can also have the layout you need.

Show the server-side generated HTML in a new window

What is the best way to show the server-side generated HTML (full page) into a new popup window? It should be triggered upon clicking a button (causing a postback to the server).
Thanks
Edited:
The HTML content are dynamically generated in the code behind and the content is full page (<html> ... </html>). Upon clicking a button on the web page, I would like to get the generated html content and pass it to the browser and show it in a new popup window. The content will be the final result (UI) not HTML tags.
You can send the same page with mime type text/plain
For instance with a
<a href="same url?mime=textonly" target="_blank">
On the asp server, when the argument mime=textonly is detected, you change the mime type to text/plain
Perhaps I should have started with a comment to get more information but can you not:
Post back to a new window on click? <a target="_blank">
Though if the requirement is for the server to generate the new window, just append something like:
<script>window.open('title'); </script> at the end of the response and have the server populate that.
You could probably have the server code save the HTML to a file and output <script>window.open('urltothefile');</script>. Just make sure that you write a unique filename each time.
Alternatively, you could have the server code store all related information into a database and output <script>window.open('showResult.aspx?id=123');</script>, where 123 is the id of the database record. Then in showResult.aspx, have it generate the required HTML.
Another option is to output the HTML into a div with style="display: none", then have some javascript to assign the innerHTML to the newly opened window. eg:
var w = window.open ('_blank');
w.document.body.innerHTML = document.getElementById("returnedHTML").innerHTML
One more possibility is to have a WebMethod. I don't really remember how to declare one, but it is a server function that can be called from the client. Open the window via javascript, call the webmethod and place the result as the innerHTML of the newly opened window; Pretty much like the previous option.
All these are good but they don't work when you use UpdatePanel and partial rendering. If that's the case, it's a whole different story.

Passing master page form data to another webform

I have a master page with one form on it. It is a search form which must always be visible. When the button of that form is clicked I want the form data to be sent to search.aspx. The problem is, I don't know how. I cannot set the form action to search.aspx, because all my other pages which use the master form will go to search.aspx. This I don't want.
Hope someone can help me out :)
Thnx.
In order to pass the values of the control "txtSearch", when Server.Transfer is executed, you could do many things, including passing it via a querystring variable or setting up a session variable, and then check either of those in the Page_Load event of Search.aspx, and if it's populated, call the event that is fired when the user would hit the submit button on the Search.aspx page.
Also, if the Search.aspx file is using the same masterpage, then you can use this.Master.FindControl("txtSearch") to get the control (it you look a the source of the file after it is generated in the browser, you'll notice that controls in the master page aren't really called by their ID, rather that have something appended to them (i.e. it would now possibly be called "ctl00_txtSearch")
You could create your search form in a separate form, and get it to use GET instead of POST.
Either that, or have the master form handle the search button click and use Server.Transfer to go to the search form.
You can have multiple forms in one page I believe. So one form (your search form) would have its action set to search.aspx and the other would be set for the page itself.
ASP.NET webform pages only have one form (which would generally be included on the master page). You can set the postback url for the search button to your search page..
<asp:Button ID="btnSearch" runat="server" Text="Search" PostBackUrl="~/search.aspx" />
..or just redirect to it from the handler in your master page like this:
protected void btnSearch_Click(object sender, EventArgs e)
{
Response.Redirect(#"~/search.aspx?q=" + Server.UrlEncode(txtSearch.Text));
}
..or use Server.Transfer as suggested by David Kemp.
Note: If you use Request.Query[#"q"] on your search page to get your query, you don't need to use Server.UrlDecode() - it's done for you.
I would:
Add some code to the master page code-behind to detect the source of the POST.
Once I have the source of the POST (e.g. the Search box). I would then pass its query to the Search form.
I used a similar process with having a HTML login form on the master page.
I posted a question and subsequent solution here - check it out:
Form Elements in ASP.NET Master Pages and Content Pages
Once I got my head round it, it seemed a pretty simple and reasonably elegant solution.
The benefit of this is that you have complete control over how the data is sent to the search form. And you don't need to enable transfer of form data to the search form and all that nasty stuff, just create a new GET request to the search page and let it do what it is supposed to do :)
Hope this helps.
NOTE:
You can only have one form with runat="server" on an ASPX page. Additional forms MUST be HTML FORMS.
Because your search form is in the master page, you can probably structure it to contain 2 forms. Place the search form tags with the action set to "search.aspx" outside of the tag that is used by the rest of the site.
<body>
<form action="search.aspx>
<!--search box and submit button-->
</form>
<form runat="server">
<!--rest of page inc placeholder-->
</form>
</body>
If the structure of the page will not enable this, you can set the submit button's PosbackUrl to point to "search.aspx". In this case, "search.aspx" would need to be coded to look in the PreviousPage property for the form data, or use Request.Form to access the input.

Categories

Resources