Is it possible to add a new ServiceReference instance to the ScriptManager on the Page during an asynchronous postback so that subsequently I can use the referenced web service through client side script?
I'm trying to do this inside a UserControl that sits inside a Repeater, that's why adding the ScriptReference programmatically during Page_Load does not work here.
EDIT 2: This is the code I call from my UserControl which does not do what I expect (adding the ServiceReference to the ScriptManager during the async postback):
private void RegisterWebservice(Type webserviceType)
{
var scm = ScriptManager.GetCurrent(Page);
if (scm == null)
throw new InvalidOperationException("ScriptManager needed on the Page!");
scm.Services.Add(new ServiceReference("~/" + webserviceType.Name + ".asmx"));
}
My goal is for my my UserControl to be as unobtrusive to the surrounding application as possible; otherwise I would have to statically define the ServiceReference in a ScriptManagerProxy on the containing Page, which is not what I want.
EDIT:
I must have been tired when I wrote this post... because I meant to write ServiceReference not ScriptReference. Updated the text above accordingly.
Now I have:
<asp:ScriptManagerProxy runat="server" ID="scmProxy">
<Services>
<asp:ServiceReference Path="~/UsefulnessWebService.asmx" />
</Services>
</asp:ScriptManagerProxy>
but I want to register the webservice in the CodeBehind.
Try something like this...
if (ScriptManager.GetCurrent(this).IsInAsyncPostBack)
{
ScriptManager.RegisterClientScriptInclude(this, this.GetType(), "script1", "~/js/myjs.js");
}
Edit:
After checking your issue, Here is the reason why it is not working:
When you add ServiceReference to ScriptManager > Services section manually in page. It adds 1 client script include directive.
e.g:
<script src="TestService.asmx/jsdebug" type="text/javascript"></script>
or
<script src="TestService.asmx/js" type="text/javascript"></script>
which provide you to accessibility to your Frontend.Web.YourScriptMethods,
Now when you add ServiceReference in async postback - It is not adding this client script inclue. So you get client script error - method is undefined.
But i figured out a workaround for this; (do not know it is right way to do it)
if (ScriptManager.GetCurrent(this).IsInAsyncPostBack)
{
ScriptManager.RegisterClientScriptInclude(this, this.GetType(), "testservice", "TestService.asmx/js");
}
You can replace the "TestService.asmx" path according to your project/web service.
This way you can achieve what you want.
Hope this helps,
Krunal Mevada
Old Ans:
Use following:
if (ScriptManager.GetCurrent(this).IsInAsyncPostBack)
{
ScriptManager.GetCurrent(this).Services.Add(new ServiceReference("~/Service.asmx"));
}
Related
I'm intending to attach my custom handler to the "DropDownClosing" event of WebDropDown.
I tried the below for a sample.
$IG.WebDropDown.prototype = {
openDropDown: function () { alert(1); }
}
But it throws error while being parsed by DOM (Uncaught ReferenceError: $IG is not defined).
Interestingly, the below one works but it shows the alert and skips all other native functionality. (e.g After alert the dropdown is not opening)
$IG.WebDropDown.prototype.openDropDown = function () { alert(1); }
The goal is, all the webdropdowns in my application should use my customer function and I want to configure this at one place rather than adding the "DropDownClosing" client event for every webdropdown.
What is the right approach to extend an event of a control in infragistics.
You can use the same client event handler for all WebDropDowns on the page, but you still have to tell each to subscribe to this handler and to use it:
<ig:WebDropDown ID="myDropDown1" runat="server">
<ClientEvents DropDownClosing="dropDownClosing" />
</ig:WebDropDown>
<ig:WebDropDown ID="myDropDown2" runat="server">
<ClientEvents DropDownClosing="dropDownClosing" />
</ig:WebDropDown>
<script type="text/javascript">
function dropDownClosing(sender, eventArgs) {
alert(1);
}
</script>
What you've tried is an override of the WebDropDown openDropDown client method. This will override the opening functionality for the control, and thus the drop down wouldn't open, unless you re-implement the functionality yourself, or use a cached reference to the original implementation. This is not the same as attaching an event handler.
I am struggling with something that I guess should be standard practice really. I have a number of user controls that use some JQuery plugins. I do not really want to link to the extra CSS and JS files from my main masterpage as this would cause extra load to the user the first time they hit the site, (admittedly it would only be the once), so I was just putting them links into the top of the user control. Then I looked at my source HTML, not nice! Even worse for controls that repeat multiple times on a page.
So I was thinking is there a way of injecting them into the Head of the page when they are needed from the User Control. For that matter is there a way of doing it to the footer for JS stuff?
To dynamically register a script (and ensure that duplicates are merged) in ASP.NET you can call:
Page.ClientScript.RegisterClientScriptInclude(
"mykey", "~/scripts/jquery-1.3.2.js");
And read the full details on this method on MSDN.
To add CSS dynamically you can do something like this:
HtmlLink cssLink = new HtmlLink();
cssLink.Href = "path to CSS";
cssLink.Attributes["some attr1"] = "some value1";
cssLink.Attributes["some attr2"] = "some value2";
Page.Header.Controls.Add(cssLink);
This example of injecting CSS will not merge duplicate entries. To avoid duplication you'll have to keep track of duplicates yourself. One place you can store a list of scripts you've already registered is in HttpContext.Items. Stick a HashSet in there that keeps a list of all registered scripts so that you don't register the same CSS file twice (which is generally harmless, but something to avoid anyway).
I followed a similar approach, but I use CSS directly in the user control so I don't have to import a CSS file. The following is code entirely from a sample user control:
<style id="style1" type="text/css" visible="false" runat="server">
td { font-family: Tahoma; font-size: 8pt; }
</style>
In code-behind:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
HtmlGenericControl style = new HtmlGenericControl("style");
style.Attributes.Add("type", "text/css");
style.InnerHtml = style1.InnerHtml;
Page.Header.Controls.Add(style);
}
You'll notice that the CSS is rendered in the head tag and not inside the body tag.
You can use ClientScript.RegisterClientScriptInclude() for the JavaScript.
For the CSS, one trick is to include them in your Master page, but with Visible="false", so that they aren't rendered into the markup by default.
Then, in your user controls, set a flag in the Items collection, from an early event, such as OnLoad(). For example, this.Context.Items["mycss"] = true;
Finally, in your Master page, from a later event, such as OnPreRender(), check to see if those flags are set. If they are, then set the Visible property to true for the corresponding CSS.
This also allows you to use the control with Master pages that don't use the CSS, since the Items entries could simply be ignored. If you have many Master pages that need the same behavior, you could put this code in a base class or use nested Master pages.
I assume you're using Asp.NET.
Try putting a content placeholder in the of the MasterPage...
<head>
<asp:ContentPlaceHolder ID="AdditionalPageHeader" />
</head>
If you're working in an aspx file or an ascx you need only define a content control...
<asp:Content ContentPlaceHolderID="AdditionalPageHeader" />
If you're working on a code-behind only type of server control, you can can get a pointer to that content place holder:
this.Page.Master.FindControl("AdditionalPageHeader")
... and manipulate it's contents programatically.
To add stylesheets or javascript (inline or not) dynamical I wrote these three functions:
Public Function addScript(ByVal path2js As String) As System.Web.UI.Control
Dim si As New HtmlGenericControl
si.TagName = "script"
si.Attributes.Add("type", "text/javascript")
si.Attributes.Add("src", path2js)
Return si
End Function
Public Function addScript_inline(ByVal js As String) As System.Web.UI.Control
Dim si As New HtmlGenericControl
si.TagName = "script"
si.Attributes.Add("type", "text/javascript")
si.InnerHtml = js
Return si
End Function
Public Function addStyle(ByVal path2css As String) As System.Web.UI.Control
Dim css As New HtmlLink
css.Href = path2css
css.Attributes.Add("rel", "stylesheet")
css.Attributes.Add("type", "text/css")
css.Attributes.Add("media", "all")
Return css
End Function
I call them in page_load on my masterpage, like this:
Me.Page.Header.Controls.Add(modGlobal.addScript("script/json/json2.js"))
or
Me.Page.Header.Controls.Add(modGlobal.addStyle("style/flexigrid/flexigrid.css"))
Regards
I am very new to jQuery and have got a quick question.
I wish to use my server side classes in my jQuery code, something similar to this:
$(document).ready(function() {
var temp = <%# myClass.Id %>;
})
Is this possible? if so, how?
Thank you very much
This is the later question I refined my former question to:
I'm sorry, I think I didn't explain myself too well... I've got a class name User. It's a class I built in my business logic.
I've got a web page named UserProfile, inside it I've got the following property exposing the current logged in user:
public BL.User CurrUser { get { return (BL.User)Session["currUser"]; } }I want to be able to access this User class from my aspx page using Jquery. How do I do that?
The databinding syntax
<%# MyStaticClass.MyProperty %>
will only work if you call DataBind on the container (page). What you're after is most likely the following syntax:
<%= MyStaticClass.MyProperty %>
which will also give you access to you page / control members
<%= this.MyPageProperty %>
As was already mentioned you should really assign those values to java script variables and pass those variables to you JS functions.
This will only work if your javascript is embedded in your source files (e.g. the .aspx files):
<script type="text/javascript">
var id = <%# myClass.Id %>; // store as raw value
var id_string = '<%# myClass.Id %>'; // store in a string
</script>
As others have said, if the JavaScript is in your aspx page, then using server tags will work fine.
If you have your jQuery in an external script file, then you could put this in your aspx page
<script type="text/javascript">
var myClass = $('#<%= myClass.ClientID %>');
</script>
and then use the variable in your external script file
$(function() {
myClass.click( function() { ... });
});
For other options take a look at this question and answer - How to stop ASP.NET from changing ids in order to use jQuery
I have the following structure on a usercontrol that is loaded by a page (Parent UC):
<UpdatePanel>
<UpdatePanel>
.. In the codebehind, it loads a Child user control at runtime
</UpdatePanel>
</UpdatePanel>
The UC has OnPageLoad registers a script.
ScriptManager.RegisterStartupScript(this, typeof(Page), "Load_" + this.ClientID, base.GetRegisterScript(this.ClientID), true);
The JS function never gets executed on async postbacks. If i remove the UpdatePanels, it works as expected
EDIT: Used this.GetType() instead of typeof(Page) but no luck
EDIT Again:
Matt - I tried to replace the typeof(Page) with the UC name. Here's the updated line:
ScriptManager.RegisterStartupScript(this, typeof(TemplateAreaTypeOne), "Load_" + this.ClientID, "...JS function here,,", true);
To clarify, the Page loads the Parent UC that has these UpdatePanels. The ParentUC then loads the ChildUC and the ScriptManager.RegisterStartuScript is used in teh ChildUC
EDIT
The markup has:
<script type="text/javascript">
//<![CDATA[
; findControl('PageLoadedHiddenTxtBox').value ='Set';OnLoadBegin('ctl00_WorkSpaceContent_ctlUnion1_ctlUnion1Child','Edit');OnLoadEnd('ctl00_WorkSpaceContent_ctlUnion1_ctlUnion1Child','Edit');
document.getElementById('ctl00_WorkSpaceContent_informationSummary').dispose = function() {
Array.remove(Page_ValidationSummaries, document.getElementById('ctl00_WorkSpaceContent_informationSummary'));
}
//]]>
</script>
Note that the functions that are called are the OnLoadBegin and OnLoadEnd that have been added to the HTML
EDIT AGAIN
Got it to work using:
ScriptManager.RegisterStartupScript(this.Page, typeof(Page),....)
Not sure why it works when I use the reference to the Page.
Will this work if I have multiple controls on the Page?
Why does it work when I use a reference to the page?
your registerstartupscript needs to target the control NOT the page dont use typeof(Page)
How do you add Javascript file programmatically to the user control?
I want the user control to be a complete package - ie I don't want to have to add javascript that's related to the user control on the page where it's used, when I can do it inside the control itself.
Since there is no Page object in the user control, how would you do it?
In the Page_Load method of control.ascx.cs file:
LiteralControl jsResource = new LiteralControl();
jsResource.Text = "<script type=\"text/javascript\" src=\"js/mini-template-control.js\"></script>";
Page.Header.Controls.Add(jsResource);
HtmlLink stylesLink = new HtmlLink();
stylesLink.Attributes["rel"] = "stylesheet";
stylesLink.Attributes["type"] = "text/css";
stylesLink.Href = "css/mini-template-control.css";
Page.Header.Controls.Add(stylesLink);
This will load css and Javascript into the head tag of the main page, just make sure that the head has runat="server".
You can register client script includes using the ClientScriptManager.
Page is accessible through the Control.Page property.
Page.ClientScript.RegisterClientScriptInclude (
typeof ( MyControl ), "includeme.js", "js/includeme.js" );
EDIT: Sorry, for a total "complete package", its possible using scripts as Embedded Resources,
and aquire dynamic URL's through the WebResource.axd handler.
If this is not considered totally complete, then i guess it could be put in App_LocalResources, but it never gonna be just one file,
unless the code and script is inline.
The same as gnomixa's response, only a bit cleaner:
HtmlGenericControl js = new HtmlGenericControl("script");
js.Attributes["type"] = "text/javascript";
js.Attributes["src"] = "jscript/formfunctions.js";
Page.Header.Controls.Add(js);
from http://www.aspdotnetfaq.com/Faq/How-to-Programmatically-add-JavaScript-File-to-Asp-Net-page.aspx
In my site I Place all needed scripts and styles to placeHolder
<asp:placeHolder runat="Server" ID="phHead">
<script src="/header/widget/script.js" type="text/javascript"></script>
<link href="/header/widget/style.css" rel="stylesheet" type="text/css" />
</asp:placeHolder>
and
Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Page.Header.Controls.Add(phHead)
End Sub
Good question!
A UserControl should be a single package without any dependency on a JavaScript or a CSS file. You will need to make the JS and CSS files as embedded resources. Right click properties and set build action to embedded resources. Then you need to inject the JavaScript and CSS files as WebResources.
Here is one article that I wrote yesterday which talks about the same scenario:
http://highoncoding.com/Articles/502_Creating_RadioButton_Validation_Using_Custom_Validator.aspx
I generally do it when rendering the HTML for the control and depending on whether it's a library injection or an instance injection I use the Items collection to specify whether or not I have already produced the code for a control of this type during the current request using a unique identifier.
Something to the effect of:
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
//Check if the Object Script has already been rendered during this request.
if (!Context.Items.Contains("xxx"))
{
//Specify that the Object Script has been rendered during this request.
Context.Items.Add("xxx", string.Empty);
//Write the script to the page via the control
writer.Write([libraryinjection]);
}
//Write the script that instantiates a new instance for this control
writer.Write([instanceinjection]);
}
If you have the text of the actual javascript in your .CS file, you can call Page.ClientScript.RegisterClientScriptBlock.
The following assumes that "GetScript()" returns the actual javascript you want added to the rendered control.
Page.ClientScript.RegisterClientScriptBlock(GetType(), "controlScriptName", GetScript());
I found this to be a more elegant way to fix-link to your javascript.
In your .ascx, link to your script files the following way:
<script src='<%= ResolveClientUrl("~/Scripts/jquery-1.7.1.min.js") %>' type="text/javascript"></script>
<script src='<%= ResolveClientUrl("~/Scripts/jquery.maskedinput-1.3.min.js") %>' type="text/javascript"></script>
That way, no matter which subfolder/page you add your user control to, the link to your scripts will always be correctly resolved.