Embedding a JS file in Silverlight Class Library - javascript

I am trying to create a Silverlight class library which needs to call a few Javascript methods. I have put these methods in a single .js file and have added it to the project. But when I try to call any of the methods in the js file, I get a FailedtoInvoke error. I understand that this problem can be solved by adding a reference of the JS file in the head section of ASPX or HTML page. But I am developing a class library and so that is not possible. Does someone know how to tackle this issue? I am using Silverlight 4 and Visual Studio 2010.

Add the .js file to your library probject as it sounds you have done, make sure it Build Action is "Resource".
You can retrieve this content with Application.GetResourceStream :-
StreamResourceInfo sriJS = Application.GetResourceStream(new Uri("YourAssemblyName;component/MyStuff.js", UriKind.Relative));
Note the structure of the Uri, the assembly name of your class library is needed followed by the literal ";component". This tells Silverlight to look for a resource inside your dll that will be included in a final application's Xap.
Now you need to turn the content of the info's Stream property into a string:-
StreamReader reader = new StreamReader(sriJS.Stream, System.Text.Encoding.UTF8);
string js = reader.ReadToEnd();
Finally you can inject that javascript into the current page with:-
HtmlPage.Window.Eval(js);
Thats it, any global functions defined in the js may now be invoked with HtmlPage.Window.Invoke.

Try something like:
string myScriptCodeString = GetScriptCodeStringFromSomewhere();
System.Windows.Browser.HtmlPage.Window.Eval(myScriptCodeString);
Then the methods defined in myScriptCodeString should be available.

Related

Referencing JavaScript file from a different assembly in a Blazor project

I have a Razor Class Library project in which I want to add a couple of custom components that use JavaScript interops. The interops work fine when I call functions that already exist in the Window object.
This, for example, works fine:
JSRuntime.InvokeVoidAsync("alert", "Hello world");
However when the functions I need are not native to the Window object, i.e. they are declared in a distinct interops.js file, I need to add a <script> tag referencing the said file in the page HTML. What is the path to that file since it resides in a different assembly?
There are two ways to approach this.
Consume static assets from a referenced RCL
From documentation
The files included in the wwwroot folder of the RCL are exposed to either the RCL or the consuming app under the prefix _content/{LIBRARY NAME}/. For example, a library named Razor.Class.Lib results in a path to static content at _content/Razor.Class.Lib/. When producing a NuGet package and the assembly name isn't the same as the package ID, use the package ID for {LIBRARY NAME}.
Read embedded asset contents using Reflection
This approach lets you execute Javascript code directly without need to include files in the HTML with <script>.
First create helper method to retrieve embedded javascript file contents:
public static string GetEmbeddedJSInteropCode(Assembly assembly, string path)
{
using var stream = assembly.GetManifestResourceStream(path);
using var reader = new StreamReader(stream);
return reader.ReadToEnd();
}
Then you can call it like this
await JSRuntime.InvokeVoidAsync("eval", GetEmbeddedJSInteropCode(typeof(SomeRCLType).Assembly, "SomeRCL.SomeFolder.Init.js"));
await JSRuntime.InvokeVoidAsync("someRCLFunction", "Foobar");
When the Razor Class Assembly is referenced in a Blazor Web Assembly project, the content of the Razor wwwroot/ folder is copied in the Blazor _content/*namespace*/ folder. So the solution is to move the .js file in the wwwroot/ and reference it in the script tag like this:
<script src="_content/*assembly_name*/file.js"></script>

ADFS 3.0 - Extending functionality

I'm currently implementing a solution consisting in ADFS 3.0 with multifactor authentication. I've followed the steps in TechNet (https://msdn.microsoft.com/en-GB/Library/dn783423.aspx?f=255&MSPPError=-2147217396) to setup the sample adapter, which works fine.
I now want to extend it and have face a few issues. I've search the web and stackoverflow for something similar but couldn't find anything so I'm posting them all here. Not sure if I need to split this into different questions:
I need to extend the adapter so that part of the html is rendered by an external script, i.e. I need to add an extra script to be loaded when the adfs adapter html is rendered.
From what I could find, one could modify the Theme to include additional javascript in the onload.js, but I don't want to go down this road, since the script really needs to be loaded externally.
The only way I can think of, and kind of works, is to inject javascript in html that loads the script dinamically, something like this:
var script =document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", <my_script_loaded_over_http>)
fileref.onload =
function() {
//call script method
};
But because the external script depends on the "onload" event of the window for some of it's logic, it doesn't work since it's loaded too late..
Is this possible at all?
Is it possible for the adapter to inject new response headers? (I'm assuming it isn't)
Is there a standard way to provide a configuration file to the adapter dll, so that some values can be changed at runtime without having to deploy a new dll? If not, is it safe to write the said configuration file to the adfs folder and read from there?
Thank you very much
I managed to figure this out by myself:
1- The interface IAdapterPresentationForm provides a method to return whatever scripts or css I want to include: string GetFormPreRenderHtml(int lcid) e.g.:
public string GetFormPreRenderHtml(int lcid){
StringBuilder sb = new StringBuilder();
sb.Append("<script src='http://myjs.js' type='text/javascript'></script>");
sb.Append("<link rel='stylesheet' type='text/css' href='http://mycss.css' />");
return sb.ToString();
}
2- Not at all
3- It's possible to pass a configuration file when registering the adapter using:
Register-AdfsAuthenticationProvider -TypeName $typeName -Name -Verbose -ConfigurationFilePath .
The pipeline will open a stream for you, and pass it in:
void OnAuthenticationPipelineLoad(IAuthenticationMethodConfigData configData)
Reference: http://blogs.recneps.net/category/ADFS

ASP.net MVC Minifying and Bundling - How to minify a single JavaScript file

In trying to keep with unobtrusive JavaScript guidelines I moved all the JavaScript out of each of my views and into a separate .js files.
However, within 1 view I need to dynamically create some JavaScript variables so these are inserted into the ViewBag and rendered directly into the view:
$(document).ready(function () {
#(ViewBag.PrePop)
#(ViewBag.PreDiscount)
});
This works fine until I had a go at using the new ASP.net bundling and minification feature.
Bundling all these small external JavaScript files together and then calling the combined script from every page means that every page (other than the one that contains the ViewBag emitted variables) has a variable reference error:
Uncaught ReferenceError: quotes is not defined
So this basically means I can't bundle this particular JavaScript file.
However, I would like to minify it. To do this, do I just declare a bundle that only contains the one JavaScript file:
bundles.Add(new ScriptBundle("~/bundles/mypagescript").Include(
"~/Scripts/mypagescript.js"));
Or is there another way to perform solely minification?
Yep, currently we don't really expose any methods for you to easily call in to Optimization just to minify a string (you could do it via an instance of JsMinify.Process if you really wanted) i.e.:
string js = "//I am a comment\r\nfoo = bar;\r\nfoo = yes;";
JsMinify jsmin = new JsMinify();
BundleContext context = new BundleContext();
BundleResponse response = new BundleResponse(js, null);
response.Content = js;
jsmin.Process(context, response);
Assert.AreEqual("foo=bar,foo=yes", response.Content);
But what you suggest is probably best (create a bundle of one file).
Sorry for the late answer ;)
You can use Microsoft.Ajax.Utilities.Minifier. Create an instance and call MinifyJavaScript - which takes a string (the JS-code) as a parameter and returns the minified code.
Dim minifier As New Microsoft.Ajax.Utilities.Minifier()
minifier.MinifyJavaScript(script)
You could then create your own HTML-helper or action to call for this. This worked well in my case atleast ;)

How to Return static HTML and/or Javascript in OpenRasta

I am using OpenRasta 2.0, and am hosting within a console application.
I would like to be able to return some static HTML pages and JavaScript files from this setup, for example:
/index.html
/jquery.js
The files are entirely static, i.e. no Handler or Resource is required.
I have added the appropriate files to the project, and initially tried the following syntax:
ResourceSpace.Has
.ResourcesOfType<object>()
.AtUri("/")
.HandledBy<HtmlHandler>()
.RenderedByAspx("~/Views/IndexView.aspx");
The .aspx file is added to the project under a folder 'Views', and is set the build action to 'Embedded Resource'. This results in a NullReferenceException at runtime when attempting to resolve the virtual path. If I set the build action of the file to 'Compile', then it will not compile, I'm guessing because the console project does not understand ASPX.
I have also tried the following shorthand syntax for this available if referencing the WebForms codec:
ResourceSpace.Has
.TheUri("/jquery.js")
.ForThePage("~/Views/jquery.js");
But this suffers from the same issues as my initial approach, although does remove the need for a dummy Handler. So as far as I can tell, the WebForms codec cannot be used within a console application because the ASPX files cannot be compiled.
I was able to return HTML using the Razor codec as this expects the view templates to be embedded. However - I was not able to return a JavaScript file with the appropriate media type using the same technique, and I had to turn my otherwise static files into .cshtml files with a #resource defined.
I can't find any examples online of returning static HTML and/or JavaScript using OpenRasta. I would expect to find a dedicated configuration API for this like the "TheUri" syntax but independent of the WebForms codec.
I could create my own 'EmbeddedFileHandler' to return the content of a static embedded file, but I feel like I'm missing something since this is such a simple use case...
Anything that depends on the asp.net pipeline being initialized (such as aspx webforms pages) cannot compile because the BuildProvider is not there to do it, mostly because webforms is too tightly coupled to the asp.net pipeline.
OR 2 was not really designed to be used as a full web stack outside of asp.net for serving static content, as usually the host environment is better suited at doing it, but that's definitly something we're going to address in 3.0.
What I'd suggest is something along the lines of registering FileInfo as a resource, create a handler that can scan the file system for the files you want, and provide your own codec that either stream the data itself or call the API for the host http listener. It should be about 20 lines of code tops and would make a great blog post. :)

Executing groovy statements in JavaScript sources in Grails

There are essentially 2 places to define JavaScript functions in Grails, directly in a element on the GSP, and within a separate javascript source file under /web-app/js (for example, application.js). We have defined a commonly reused javascript function within application.js, but we also need to be able to generate parts of the function dynamically using groovy code. Unfortunately, ${some groovy code} does not appear to be processed within separate javascript source files.
Is the only way to do this by defining the javascript function within a script tag on a GSP page, or is there a more general solution? Obviously we could define the javascript function in a script tag within a template GSP file which would be reused, but there is a lot of push to keep our javascript functions defined all together in one place (i.e. the external javascript source file). This has performance benefits as well (the javascript source files are usually just downloaded once by each client's browser, instead of reloading the same javascript functions within the source of every html page they visit). I have toyed around with the idea of breaking the function up into static and dynamic pieces, putting the static ones in the external source and putting the dynamic ones in the template GSP, then gluing them together, but this seems like an unnecessary hack.
Any ideas?
(edit: It may sound like the idea of dynamically generating parts of a JavaScript function, which is then downloaded once and used over and over again by the client, would be a bad idea. However, the piece which is "dynamic" only changes perhaps once a week or month, and then only very slightly. Mostly we just want this piece generated off the database, even if only once, instead of hard coded.)
An easy solution to keep your JavaScript unobtrusive is to create a JavaScriptController and map its actions "/js/*" by adding this to your UrlMappings.groovy file:
"/js/$action"{
controller = "javascript"
}
then just create an action for each dynamic JS file you want, include in in your layout <HEAD>, and presto, you've got a JS file that you can insert Grails snippets into! :)
Note: I've found that there's currently a bug in Grails that doesn't map file extensions to content-types properly, so you'll need to include <%# page contentType="text/javascript; UTF-8" %> at the top of your view files.
This is a great solution. I would like to offer a suggestion to use somthing other then a mapping of "/js/$action" because this is no longer going to allow you to access you javascript files in /web-app/js/. All your javascript files would have to be moved to a the directory your controller would point to.
I would use something like
"/dynjs/$action"
This way you still can point to files in the /web-app/js/ files with out conflict and enjoy the benifits of gsp tags in javascript files
Please correct me if I'm wrong.
Or this... have a tag/service/dynamic method that lets tags write out their JS+CSS+whatever else, to a "cache" which is used to build the JS+CSS resources by a different controller.
Full concept here: [http://www.anyware.co.uk/2005/2009/01/19/an-idea-to-give-grails-tags-esp/][1]
If you want to use models created by the controller (that rendered HTML page which reference the Javascript in which you intend to use groovy code) in the Javascript code, then you can use this technique:
This technique does not need to change URL mappings and does not require you to create extra controller.
In your view GSP add javascript as follows:
<script type="text/javascript">
<g:render template="/javascript/yourJavascriptFile"/>
</script>
In views folder create a "javascript" folder. And create a file named:
_yourJavascriptFile.gsp
You can not only use all the GSP code in your _yourJavascriptFile.gsp file, but you can also use all the models created in your controller (that is rendering the view).
NOTE: There is nothing special about javascript folder. You can name it anything you want OR use an existing view folder. This is just a matter of organizing and identifying your HTML spitting GSP from Javascript spitting GSPs. Alternatively, you can use some naming conventions like: _something.js.gsp etc.
Name your scripts like this
/wherever/the/js/files/are/thescript.js.gsp
The gsp code inside will be rendered correctly by grails. This works, but I have no idea if it's considered a Good Idea or not.
There is another way - pass in the generated code into a function that expects closures. Those closures is generated by the program of course. The generated code is of course inlined/script-tagged in the gsp page.
it may or may not work depending on the nature of the code being generated. But i suspect it will work, and if it doesnt, minor tweaking to the coding style of your javascript will definitely make it work. Though, if these 'generated' code doesnt change much, this quite overkill imo.

Categories