We wrote a couple of controls using Microsoft AJAX (cs class + js class). Now I'm thinking about getting rid of it (just use jQuery), as it is bloated and we don't use UpdatePanel. My question is: how should I change my controls? Right now they implement IScriptControl, which uses Microsoft AJAX features (if I understand correctly, ScriptManager & ScriptControlDescriptor classes). What to use instead?
CLARIFICATION. I don't need some more JavaScript libraries - I'm already using jQuery and would like to minimize additional includes (unless they are really small). What I need is replacement for ScriptManager and IScriptControl interface. Things like:
Registering script references (and
not duplicating them).
Instantiating script class associated with control.
Binding my class to DOM element (what is the best way to do that using jQuery, btw?).
Initializing JS class fields.
On the other hand, you can try comet ajax approach, check these samples.
Ok, I finally finished it.
We ended up creating Page descendant with the some code in it to substitute for script manager (see below). We call to it from control's OnPreRender method using control's Page property. Thanks to guys from http://dj.codeplex.com/ for providing example of how to do it.
2, 3, 4. We used jQuery.data method to bind instances of script classes to DOM elements. We execute instantiation, initialization and binding code using jQuery.ready method. This code is added to control in its Render method using AddScript method (see below). Maybe later we would use JavaScriptSerializer for passing values from C# control to javascript classes, but at the moment we do it by hands, passing parameters to javascript class constructor.
HashSet<string> scriptReferences = new HashSet<string>();
HashSet<string> cssReferences = new HashSet<string>();
List<string> styles = new List<string>();
public void AddScriptReference(string url, bool resolve)
{
string realUrl = url;
if (resolve)
realUrl = ResolveClientUrl(url);
if (!scriptReferences.Contains(realUrl))
{
scriptReferences.Add(realUrl);
Header.Controls.Add(
new LiteralControl(
"<script type='text/javascript' src='" +
realUrl + "'></script>"));
}
}
public void AddCssReference(string url)
{
if (!cssReferences.Contains(url))
{
cssReferences.Add(url);
HtmlLink link = new HtmlLink();
//link.Href = ResolveClientUrl("~/jQuery-ui/css/ui-lightness/jquery-ui.css");
link.Href = url;
link.Attributes.Add("type", "text/css");
link.Attributes.Add("rel", "stylesheet");
Header.Controls.Add(link);
}
}
public void AddCssStyle(string style)
{
styles.Add(style);
}
protected override void OnPreRenderComplete(EventArgs e)
{
base.OnPreRenderComplete(e);
Header.Controls.Add(
new LiteralControl(
"<style type='text/css'>" + styles.Join("\n") + "</style>"
)
);
}
public static void AddScript(HtmlTextWriter writer, string script,
bool executeWhenReady)
{
writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/javascript");
writer.RenderBeginTag(HtmlTextWriterTag.Script);
if (executeWhenReady)
{
writer.Write("$(function(){\n");
}
writer.Write(script);
if (executeWhenReady)
{
writer.Write("});\n");
}
writer.RenderEndTag();
}
jQuery and jQuery UI are very powerful. But you also have access to Moo Tools and Prototype. Which tools in MS AJAX are you using? There are pretty much something comparable in open source non-MS offerings across the board. They just require slightly more labor on your part to implement. You might also look at Telerik and Syncfusions controls. Telerik has a bunch of open source ajax offering for ASP.NET MVC which can be converted to ASP.NET Web Forms pretty easily.
You may be interested in the more lightweight conditional rendering feature in the upcoming release of .NET4 (along with Visual Studio 2010)
http://msdn.microsoft.com/en-us/magazine/ee335716.aspx
If you can wait, it might be a viable solution for you.
I'm not sure you need a replacement for IScriptControl and the Scriptmanager if you want to strictly use jQuery. I recommend you check out some http://blog.jeremymartin.name/2008/02/building-your-first-jquery-plugin-that.html'>tutorials on creating jQuery plugins.
Related
After deploying a new version of a website the browser loads everything from its cache from the old webpage until a hard, force refresh is done.
In ASP.NET MVC if the file becomes in Bundle, it handled by Optimization framework. a version added to your file link, and if a change occurs in your bundle's file a new token generate. follow below code :
for example, js file name is: datatables
when you put it in a bundle with the same name, you will see the
datatables?v=anY9_bo7KitrGnXQr8ITP3ylmhQe9NDzSjgLpLQWQFE1
as a file name.
change datatables and watch again the name of the file in the browser, surely it will change:
datatables?v=r8yhQBxKyDgrOGyqr1ndtdG92Ije09nqTY7yogrOSTk1
But there's two questions:
What we can do if our file wasn't in Bundle?
Is a way to force the browser to refresh cache?
we have one solution with some different way for implementation. we use above solution for it.
datatables?v=1
we can handle the version of the file, it's mean that every time that we change our file, change the version of it too. but it's not a suitable way.
another way used Guide, it wasn't suitable too, because each time it fetches the file and doesn't use from the browser cache.
datatables?v=Guid.NewGuid()
The last way that is the best Way is :
when file change occur , change version too. check follow code :
<script src="~/scripts/main.js?v=#File.GetLastWriteTime(Server.MapPath("/scripts/main.js")).ToString("yyyyMMddHHmmss")"></script>
by this way, when you change the file, LastWriteTime change too, so the version of the file will change and in the next when you open the browser, it detects a new file and fetch it.
Assuming you cannot use bundling for some reason, the solution suggested by the original poster is good enough, however it's better to put the logic inside a helper method.
It makes the code testable, it helps to change the logic without changing .cshtml , and also helps to not repeat the filename twice. Then you can have have a much cleaner code:
<script src="#Url.ContentWithVersion("~/scripts/main.js")"></script>
To do so, you can add ContentWithVersion extension method to the existing UrlHelper:
using System;
using System.IO;
using System.Web;
using System.Web.Mvc;
public static class UrlHelperExtensions
{
public static string ContentWithVersion(this UrlHelper urlHelper, string path)
{
if (urlHelper == null)
throw new ArgumentNullException(nameof(urlHelper));
var result = urlHelper.Content(path);
var file = HttpContext.Current.Server.MapPath(path);
if (File.Exists(file))
result += $"?v={File.GetLastWriteTime(file).ToString("yyyyMMddHHmmss")}";
return result;
}
}
I've been given the task of updating an old OCX using C#. Everything works fine apart from one thing.
I've now been told that we need to add in a Param specifying a port.
The old HTML looked like this:
<object classid="clsid:D636293D-5687-4847-B53E-D4B4F3FABAD0" id="ActiveXTest3">
<param name="Port" value="8085" />
</object>
The main requirement is that the code to display the control is kept in a static html page.
No Javascript allowed (not sure why but it's what I've been told!)
Now doing some digging some posts say its not possible in .NET. Some say it is possible but hosting the object as an ASPX page. I've found some reference to using
IPropertyBag
in my C# ActiveX Control but can't find any definitive solution or answer.
Can someone clear this up and if possible a simple example?
use a com visible interface and place there something like
String Text { set;get;}
And, In the control class place something like
public String Text
{
get
{
return mStr_Text;// mStr_Text is private variable declared in the control class//
}
set
{
mStr_Text = value;
this.label1.Text = value.ToString();// will change the label's Text
}
}
After that you can place the param name as Text.
I would like to extend the functionality of vbscript with the code I have written in c#. I have written some classes to automate the SAP GUI and would like to use these classes in all the vbscript files I have.
I have hundreds of vbscript files and know it will take years to convert all them to C#. So I think it will be faster to expose my c# classes to vbscript.
Do you know how to do this or know any references online I can study?
I don't know whether you're running your VBScript from the command-line or from within something like Office.
If the former, you could create one or more command-line apps that you can call from any scripting language and into which you pass parameters & action specifiers just like any other command-line tool. (Also consider moving to PowerShell in this case - it exponentially better than VBScript for command-line scripting & has great integration with .NET).
If the latter, you'll likely need to register your C# classes using RegAsm and then create instances of your C# types as per any other COM type. See this post for more details: How do I call .NET code (C#/vb.net) from vbScript?
VB script runs on the client inside the browser run-time.
The only C# solution I am aware of to run inside the browser, is silverlight. It is still just c# though.
You can access c# code from scripting languages like VB- of java-script, by decorating them with the [ScriptableMember] attribute, like so:
/// <summary>
/// Members that can be called from javascript. (or vbscript)
/// </summary>
public sealed class LINEARVIEWER_SL_SCRIPTS {
[ScriptableMember]
public void ChangeNetwork(string pNetworkFilterId, string pNetworkFilter) {
MainViewModel MainVM = (MainViewModel)((MainPage)Application.Current.RootVisual).DataContext;
long SectionID;
if (long.TryParse(pNetworkFilterId, out SectionID) == false) {
throw new FormatException("'" + pNetworkFilterId + "' not a valid section / network ID.");
}
MainVM.RoadFilterViewModel.SelectSectionAsync(SectionID, /* completed handler = */ null);
}
}
You have to register these classes when the silverligh (c#) application starts up, like so:
private void Application_Startup(object sender, StartupEventArgs e) {
...
HtmlPage.RegisterScriptableObject("LINEARVIEWER_SL_SCRIPTS", new LINEARVIEWER_SL_SCRIPTS());
}
From the java (or vb) script, you can then simply call those methods like so:
function DoAddToLIV(pNetworkFilterId, pNetworkFilter) {
...
gObjLIV.Content.LINEARVIEWER_SL_SCRIPTS.ChangeNetwork(pNetworkFilterId, pNetworkFilter);
...
}
where gObjLIB.Content is the id of the silverlight object inside the html page.
var gObjLIV = null;
function onSilverlightPluginLoaded(sender, args) {
gObjLIV = sender.getHost();
}
You can hook that function to the silverlight object in the html of ASPX page, using this parameter:
<param name="onLoad" value="onSilverlightPluginLoaded" />
Let me know if I missed anything or if you need more examples. I don't mind.
*Please note that this is not for a web based application, it's windows based.
I'm building an application where I will need the user to submit simple javascripts that will be run by the application.
The scripts will call functions that are part of the c# build.
An example:
C# code:
public void helloWorld()
{
Debug.WriteLine("hello world");
}
Javascript submitted by user:
helloWorld();
The JavaScript would be parsed by the application at runtime and then call the required functions in my C# code.
Why?..
My app will be used by people with very little programming experience, they enter very simple JavaScripts and the app will attempt to automate a few tasks on the users computer. So my reason for using JavaScript is because it's simple and very easy to learn for someone with little experience.
It sounds like you want a JavaScript parser for your application. To be honest, I dont think what you're doing is possible, considering the context of the script and your code is different. However, this project seems to be doing something that may get you to the right place:
http://javascriptdotnet.codeplex.com/
Personally, I would think making some kind of XML format would be useful (like how UrlRewriter.net makes rewriting URLs easy):
<xml>
<commands>
<!-- Expose a Set of Condition Objects to Select From -->
<if condition="YourApplication.Conditions.RightClickOnDesktop">
<print text="HelloWorld" />
</if>
</commands>
Here is an example running a javascript code which, in turn, invokes a c# method
[System.Runtime.InteropServices.ComVisible(true)]
public class CSharpClass
{
public void MsgBox(string s)
{
MessageBox.Show(s);
}
}
-
Type scriptType = Type.GetTypeFromCLSID(Guid.Parse("0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC"));
dynamic obj = Activator.CreateInstance(scriptType, false);
obj.Language = "Javascript";
obj.AddObject("mywindow", new CSharpClass(), true);
var result = obj.Eval(
#"
function test(){
mywindow.MsgBox('hello');
}
test();
"
);
Why do you "need the user to submit simple javascripts"? What is your application and what do users need it to do? Why have you decided a scripting language is the way to do this? I'm not saying that is the wrong answer, but that you have not justified this conclusion.
If your app will be used by "people with very little programming experience" I do not recommend implementing a scripting language. Basic concepts like source code and variables are very difficult for non-programmers to understand.
I suggest first investigating macro recording for user scripting. For .NET there is UI Automation and the White automation framework.
This may be a long shot, but I'm using ComponentOne's Spellchecker control for Silverlight. I made a test project, added a plain textbox and a button to it, added the references to the C1.Silverlight and C1.Silverlight.SpellChecker bits, and added the dictionary file to my project.
In the code, I called up the spellchecker on button1's click event and it worked SPLENDIDLY. The spellchecker dialog shows up, and works exactly as it should.
Since that test was successful, I then tried to implement this into my existing project. I've had no success for absolutely NO reason that I can determine, since I used the EXACT SAME code.
Here's the code I use to call the component:
using C1.Silverlight;
using C1.Silverlight.SpellChecker;
using C1.Silverlight.Resources;
public partial class MainPage : UserControl
{
C1SpellChecker spellChecker = new C1SpellChecker();
public MainPage()
{
InitializeComponent();
spellChecker.MainDictionary.LoadAsync("C1Spell_en-US.dct");
}
private void btnSpelling_Click(object sender, RoutedEventArgs e)
{
var dlg = new C1SpellDialog();
spellChecker.CheckControlAsync(txtArticle, false, dlg);
}
The references to C1.Silverlight and C1.Silverlight.Spellchecker are added to this project as well, and the dictionary as been added in the same fashion as well. The issue seems to be that for whatever reason the dictionary is not loading, because the spellChecker.Enabled method returns whether or not the main dictionary has been loaded. If I call MessageBox.Show("SpellChecker Enabled = " + spellChecker.Enabled.ToString()); it shows false, even though the call to load the dictionary is there (as you can see).
What would cause the dictionary to not load? Have I added it to my project incorrectly somehow?
EDIT: I suspect that I have added the dictionary to the project incorrectly, because the ComponentOne reference states:
If C1SpellChecker cannot find the
spelling dictionary, it will not throw
any exceptions. The Enabled property
will be set to false and the component
will not be able to spell-check any
text.
I just don't know what's wrong though because it was added in the same way that it was in the test project (Right clicked on the project.web->Add->Existing Item)
As always, thank you!
-Sootah
You could add the dictionary to the Silverlight app as an embedded resource and then load it using this code:
public MainPage()
{
InitializeComponent();
// load C1SpellChecker dictionary from embedded resource
var asm = this.GetType().Assembly;
foreach (var res in asm.GetManifestResourceNames())
{
if (res.EndsWith(".dct"))
{
using (var s = asm.GetManifestResourceStream(res))
{
sc.MainDictionary.Load(s);
break;
}
}
}
}
I think this post is duplicated in our forum as well, but will answer first here. Please try this:
1) Try to access the .dct file using your browser. If you cannot see it, it's probably because your web server is not serving that type of files. You need ton configure the web server to allow it.
2) verify the URL you are using is correct.http://helpcentral.componentone.com/CS/silverlight_161/f/78/p/86955/241328.aspx#241328
3) Check you are setting everything correctly: http://helpcentral.componentone.com/CS/silverlight_161/f/78/p/81924/227790.aspx#227790
Hope this helps!