Trigger System.Windows.Forms dll using javascript ActiveX object - c#

I am developing a C++ custom wizard with 1 page UI consisting of a dropdown control.
I want to populate this dropdown control with all input languages installed on that machine.
(An input language is a culture/keyboard layout pair that determines how the physical keys on a keyboard map or plot to characters in a language.)
I am trying to get this list & have found a way to do in C#.
public void GetLanguages() {
// Gets the list of installed languages.
foreach(InputLanguage lang in InputLanguage.InstalledInputLanguages) {
textBox1.Text += lang.Culture.EnglishName + '\n';
}
}
No i want to implement the same using javascript as my custom wizard uses .js
I tried doing below, but getting the js runtime error: "Automation Server can't create object".
<select class="sideBtn" size="1" id="LANGUAGE_LISTBOX" accesskey="L" title="Select Languages:">
<script type="text/javascript">
var obj = new ActiveXObject("System.Windows.Forms");
// Gets the list of installed languages.
for (var lang in obj.Windows.Forms.InputLanguage.InstalledInputLanguages)
{
document.write('<option value="' + lang.Culture.EnglishName + '">' + lang.Culture.EnglishName + '</option>');
}
</script>
</select>
I have tried like this as i have referred other articles which shows trigerring a c# dll using javascript ActiveX object.
Triggering C# dll using Javascript ActiveX Object
Can some one help me please??
Regards,
Deepthi

You can't do what you want using this code, because there is no COM object registered as System.Windows.Forms. But the question you've linked to, is exactly what you want.
You have two options to implement this and selecting one of them depends on whether you want to have just the culture names in Javascript side or the whole InputLanguage class. I think the first approach will be enough for you here. For the second one, you should define an interface and a new class that contain all the properties of InputLanguage you need in Javascript.
In the interface IHello, change this:
[DispId(1)]
string GetLanguages();
In the class CHello, change this:
public string GetLanguages()
{
string[] langNames =InputLanguage.InstalledInputLanguages
.OfType<InputLanguage>()
.Select(lang => string.Format("{0}", lang.Culture.EnglishName))
.ToArray();
// This is a simple Join, just to give you the idea
// You better use a proper serialization like JSON
return string.Join(";", langNames);
}
And your javascript code (suppose you either reduced the security levels, or signed you ActiveX):
<script type="text/javascript">
myAx1 = new ActiveXObject("csharpAx.CHello");
if(myAx1 != null)
{
// Gets the list of installed languages.
for (var lang in obj.GetLanguages().split(";"))
{
document.write('<option value="' +
lang +
'">' +
lang +
'</option>');
}
}
</script>

Related

Invoke JavaScript from C# code behind [duplicate]

This question already has answers here:
Calling JavaScript Function From CodeBehind
(21 answers)
Closed 9 years ago.
I am trying to learn asp.net. Assuming that I have this code:
if (command.ExecuteNonQuery() == 0)
{
// JavaScript like alert("true");
}
else
{
// JavaScript like alert("false");
}
How to I can invoke JavaScript from C# code behind? How to do that by putting that JavaScript in Scripts directory which is created by default in MS Visual Studio?
Here is method I will use from time to time to send a pop message from the code behind. I try to avoid having to do this - but sometimes I need to.
private void LoadClientScriptMessage(string message)
{
StringBuilder script = new StringBuilder();
script.Append(#"<script language='javascript'>");
script.Append(#"alert('" + message + "');");
script.Append(#"</script>");
Page.ClientScript.RegisterStartupScript(this.GetType(), "messageScript", script.ToString());
}
You can use RegisterStartupScript to load a javascript function from CodeBehind.
Please note that javascript will only run at client side when the page is render at client's browser.
Regular Page
Page.ClientScript.RegisterStartupScript(this.GetType(), "myfunc" + UniqueID,
"myJavascriptFunction();", true);
Ajax Page
You need to use ScriptManager if you use ajax.
ScriptManager.RegisterStartupScript(Page, Page.GetType(), "myfunc" + UniqueID,
"myJavascriptFunction();", true);
Usually these "startupscripts" are handy for translations or passing settings to javascript.
Although the solution Mike provided is correct on the .Net side I doubt in a clean (read: no spaghetti code) production environment this is a good practice. It would be better to add .Net variables to a javascript object like so:
// GA example
public static string GetAnalyticsSettingsScript()
{
var settings = new StringBuilder();
var logged = ProjectContext.CurrentUser != null ? "Logged" : "Not Logged";
var account = Configuration.Configuration.GoogleAnalyticsAccount;
// check the required objects since it might not yet exist
settings.AppendLine("Project = window.Project || {};");
settings.AppendLine("Project.analytics = Project.analytics || {};");
settings.AppendLine("Project.analytics.settings = Project.analytics.settings || {};");
settings.AppendFormat("Project.analytics.settings.account = '{0}';", account);
settings.AppendLine();
settings.AppendFormat("Project.analytics.settings.logged = '{0}';", logged);
settings.AppendLine();
return settings.ToString();
}
And then use the common Page.ClientScript.RegisterStartupScript to add it to the HTML.
private void RegisterAnalyticsSettingsScript()
{
string script = GoogleAnalyticsConfiguration.GetAnalyticsSettingsScript();
if (!string.IsNullOrEmpty(script))
{
Page.ClientScript.RegisterStartupScript(GetType(), "AnalyticsSettings", script, true);
}
}
On the JavaScript side it might look like this:
// IIFE
(function($){
// 1. CONFIGURATION
var cfg = {
trackingSetup: {
account: "UA-xxx-1",
allowLinker: true,
domainName: "auto",
siteSpeedSampleRate: 100,
pluginUrl: "//www.google-analytics.com/plugins/ga/inpage_linkid.js"
},
customVariablesSetup: {
usertype: {
slot: 1,
property: "User_type",
value: "Not Logged",
scope: 1
}
}
};
// 2. DOM PROJECT OBJECT
window.Project = window.Project || {};
window.Project.analytics = {
init: function(){
// loading ga.js here with ajax
},
activate: function(){
var proj = this,
account = proj.settings.account || cfg.trackingSetup.account,
logged = proj.settings.logged || cfg.customVariablesSetup.usertype.value;
// override the cfg with settings from .net
cfg.trackingSetup.account = account;
cfg.customVariablesSetup.usertype.value = logged;
// binding events, and more ...
}
};
// 3. INITIALIZE ON LOAD
Project.analytics.init();
// 4. ACTIVATE ONCE THE DOM IS READY
$(function () {
Project.analytics.activate();
});
}(jQuery));
The advantage with this setup is you can load an asynchronous object and override the settings of this object by .Net. Using a configuration object you directly inject javascript into the object and override it when found.
This approach allows me to easily get translation strings, settings, and so on ...
It requires a little bit knowledge of both.
Please note the real power of tis approach lies in the "direct initialization" and "delayed activation". This is necessary as you might not know when (during loading of the page) these object are live. The delay helps overriding the proper objects.
This might be a long shot, but sometimes I need a c# property/value from the server side displaying or manipulated on the client side.
c# code behind page
public string Name {get; set;}
JavaScript on Aspx page
var name = '<%=Name%>';
Populating to client side is generally easier, depending on your issue. Just a thought!

Using jQuery .load() with aspx

So I'm fairly new to the .NET framework, but what I'm trying to do is execute the following jQuery code:
$(document).on('click', 'a[data-link]', function () {
var $this = $(this);
url = $this.data('link');
$("#imagePreview").load("imageProcess.aspx?"+url);
where url holds something like "model=2k01&type=black&category=variable".
Unfortunately this doesn't work, becuase when I do something as simple as a Response.Write() in the aspx file, the div tag imagePreview doesn't do anything. However, removing the ? + url part works, but then I can't send any data over to the aspx file. I'm doing it this way because every link a[data-link] has different data that's being sent over, and I need to find a dynamic way to achieve this. Any suggestions would be much appreciated.
UPDATE:
Here is the part in my html code that is generating the url stuff:
<a class='modelsBlue' href = '#' data-link='model=" + $(this).find('model').text() + "&type=" + category + "'>" + $(this).find("model").text() + "</a>
and #image preview is in my code as:
<div id = "imagePreview"></div>
When I try to run the code above, i get the following error which seems to be coming from the jQuery.js file:
Microsoft JScript runtime error: Syntax error, unrecognized expression: &type=AutoEarly
Here is the imageProcess.aspx.cs file, which right now is just outputting all images in the directory:
namespace ModelMonitoring
{
public partial class imageProcess : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.Write("test");
foreach (var f in Directory.GetFiles(Directory.GetCurrentDirectory()))
{
Response.Write(f);
Response.Write("<br />");
}
}
}
}
SECOND UPDATE:
I don't get the error running in chrome or firefox, but the files are not being output.
Turns out it was a whitespace issue. I had to add a wrapper around:
$(this).find('model').text()
to read:
$.trim($(this).find('model').text())
becuase the xml file I was reading from had whitespace around the model name. Thanks to anyone who replied!

Syntax for using C# to create multiple HTML attributes via attributes.add

This is long-winded but should be easy for one of you knowledgable chaps to workout.
I have a DotNetNuke webpage with a dynamic login link. If you are not logged in the link will be 'login' and have the appropriate URL to a login popup. If you are logged in the link will be 'logout' and likewise have an the appropriate URL to the webpage that handles logout.
When the page determines if you are logged in or not the HTML link gets built with an attribute of : onclick="return dnnModal.show('http://blahblah.com....').
The code that does this:
loginLink.Attributes.Add(" onclick", "return " + UrlUtils.PopUpUrl(loginLink.NavigateUrl, this, PortalSettings, true, false, 200, 550));
Regardless of what the link is, the ID and Class always remain the same. My problem is that I would like to replace the login text with an image, infact a different image for login and logout. The issue here is that because the ID and Class stay the same I can't just do it via CSS as I normally would, but I have been able to style classes based on their attributes. I have tested this by finding out the output of the creation of the HTML link and styling the class based on the 'href' attribute for example:
a #dnn_dnnLogin_loginLink .LoginLink [href="http://some very very long dynamically created URL.aspx"]{ styles here }
The problem with this is the login/logout links change based on what page you are currently on.
I do know that each of the two rendered options has a uniqe attribue that I could style and that's their "Text" attribute. So quite simply how do I add this attribute to be rendered in HTML so that I can style it with CSS?
I have tried several variations such as:
loginLink.Attributes.Add(" onclick", "return " + UrlUtils.PopUpUrl(loginLink.NavigateUrl, this, PortalSettings, true, false, 200, 550) " Text", + loginLink.Text);
In the hope that what would be rendered would be something like:
onclick="return dnnModal.show('http://localhost/CPD/tabid/87/ctl/Login/Default.aspx?returnurl=%2fCPD.aspx&popUp=true',/*showReturn*/true,200,550,true,'')" Text="Login"
So I could style:
a #dnn_dnnLogin_loginLink .LoginLink [Text="Login"]{styles here}
a #dnn_dnnLogin_loginLink .LoginLink [Text="Logout"]{styles here}
But instead I get a generic error. I have tried various ways of writing the line without success, I just don't know the syntax.
Could someone point me in the right direction? I so hope I'm not barking up the wrong tree as this would be a really simple solution to my initial problem.
Thanks,
Edit - Code for the whole page if that helps?
using System;
using System.Web;
using System.Web.UI;
using DotNetNuke.Common;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Services.Exceptions;
using DotNetNuke.Services.Localization;
using DotNetNuke.UI.Modules;
namespace DotNetNuke.UI.Skins.Controls
{
public partial class Login : SkinObjectBase
{
private const string MyFileName = "Login.ascx";
public string Text { get; set; }
public string CssClass { get; set; }
public string LogoffText { get; set; }
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
try
{
if (!String.IsNullOrEmpty(CssClass))
{
loginLink.CssClass = CssClass;
}
if (Request.IsAuthenticated)
{
if (!String.IsNullOrEmpty(LogoffText))
{
if (LogoffText.IndexOf("src=") != -1)
{
LogoffText = LogoffText.Replace("src=\"", "src=\"" + PortalSettings.ActiveTab.SkinPath);
}
loginLink.Text = LogoffText;
}
else
{
loginLink.Text = Localization.GetString("Logout", Localization.GetResourceFile(this, MyFileName));
}
loginLink.NavigateUrl = Globals.NavigateURL(PortalSettings.ActiveTab.TabID, "Logoff");
}
else
{
if (!String.IsNullOrEmpty(Text))
{
if (Text.IndexOf("src=") != -1)
{
Text = Text.Replace("src=\"", "src=\"" + PortalSettings.ActiveTab.SkinPath);
}
loginLink.Text = Text;
}
else
{
loginLink.Text = Localization.GetString("Login", Localization.GetResourceFile(this, MyFileName));
}
string returnUrl = HttpContext.Current.Request.RawUrl;
if (returnUrl.IndexOf("?returnurl=") != -1)
{
returnUrl = returnUrl.Substring(0, returnUrl.IndexOf("?returnurl="));
}
returnUrl = HttpUtility.UrlEncode(returnUrl);
loginLink.NavigateUrl = Globals.LoginURL(returnUrl, (Request.QueryString["override"] != null));
if (PortalSettings.EnablePopUps && PortalSettings.LoginTabId == Null.NullInteger)
{
loginLink.Attributes.Add(" onclick", "return " + UrlUtils.PopUpUrl(loginLink.NavigateUrl, this, PortalSettings, true, false, 200, 550));
}
}
}
catch (Exception exc)
{
Exceptions.ProcessModuleLoadException(this, exc);
}
}
}
}
CSS classes are just designed for this purpose, and they are supported by all browsers that use CSS styling (even very old ones). You don't have to fight around with obscure selectors that are referencing some link that could change and break your styling again.
Since you said you already have a class assigned to these tags, you just want to specify an additional one. You can have more than one class assinged to a tag. See the W3C css class page for more info, in section 'Attribute Values':
Specifies one or more class names for an element. To specify multiple
classes, separate the class names with a space, e.g. . This allows you to combine several CSS classes for one
HTML element.
You can set the second class simply by appending it to the WebControl.CssClass string, separated by a space:
loginLink.CssClass = loginLink.CssClass + " login";
or
loginLink.CssClass = loginLink.CssClass + " logout";
this way you can access it via a single class selector or even the multiple class selector (only selects those tags that have both classes assigned) in your CSS style sheet:
.LoginLink.login { /* styles here */ }
.LoginLink.logout { /* styles here */ }
The text on the login/logout button is not stored in the Text="" attribute, but in the InnerHTML node. So your CSS selector would not apply. (I also think that the spacings in the selector are wrong, and that this solution would not support multilingual buttons, etc.)
Usually this type of styling would be implemented by in the Skin Editor (Admin/Skins/scroll down to section Skin Designer), where you select Skin or Container, File, Token=LOGIN, Setting=Text and LogoffText, and add a value src=path/to/a.gif. However, the skin designer seems to be broken in 6.1.x (bug report)
You might still try and have a look at the login.ascx and login.ascx.cs files in the admin\Skins directory of your DNN installation. Edit the code to assign loginLink.ImageUrl depending on Request.IsAuthenticated.

Binding Data to YUI Treeview control in c#

How can I bind data to YUI Treeview control http://developer.yahoo.com/yui/examples/treeview/default_tree.html
here is sample JavaScript code that have been used in the above URL
<div id="treeDiv1">
</div>
<script type="text/javascript">
var tree;
(function() {
function treeInit() {
buildRandomTextNodeTree();
}
function buildRandomTextNodeTree() {
tree = new YAHOO.widget.TreeView("treeDiv1");
for (var i = 0; i < 5; i++) {
var tmpNode = new YAHOO.widget.TextNode("label-" + i, tree.getRoot(), false);
buildLargeBranch(tmpNode);
}
tree.draw();
}
function buildLargeBranch(node) {
if (node.depth < 8) {
YAHOO.log("buildRandomTextBranch: " + node.index, "info", "example");
for (var i = 0; i < 8; i++) {
new YAHOO.widget.TextNode(node.label + "-" + i, node, false);
}
}
}
YAHOO.util.Event.onDOMReady(treeInit);
})();
</script>
The problem is, YUI treeview control is binded in javascript, but I want to bind in C# code, because I need to get data from Database, here is how I am binding data to asp.net treeview control
if (dsSalesRepresent.Tables[0].Rows.Count > 0)
{
dsSalesRepresent.Relations.Add("Children", dsSalesRepresent.Tables[0].Columns["NodeId"], dsSalesRepresent.Tables[0].Columns["ParentId"]);
trvSalesRepresent.Nodes.Clear();
foreach (DataRow masterRow in dsSalesRepresent.Tables[0].Rows)
{
if (masterRow["ParentId"].ToString() == "")
{
TreeNode masterNode = new TreeNode((String)masterRow["JobTitle"], Convert.ToString(masterRow["NodeId"]));
trvSalesRepresent.Nodes.Add(masterNode);
TreeNode FirstchildNode = new TreeNode((String)masterRow["UserName"], Convert.ToString(masterRow["ParentId"]));
masterNode.ChildNodes.Add(FirstchildNode);
foreach (DataRow childRow in masterRow.GetChildRows("Children"))
{
TreeNode childNode = new TreeNode((String)childRow["UserName"], Convert.ToString(childRow["ParentId"]));
masterNode.ChildNodes.Add(childNode);
}
}
}
trvSalesRepresent.ExpandAll();
}
All of my comments are assuming you mean WebForms and not MVC.
The YUI framework is purely client side. It is intended to be able to used with any website regardless of the server platform. The ASP.NET tree view is used only with ASP.Net and so doesn't have that limitation. It is a server control and so it actually emits everything the client needs even though it looks like you are binding directly to it.
A couple of options, but there's lots:
Use an AJAX/JSON to call back to your website to get the data in JSON format which you can then handle client side.
Just the way that you're asking this question makes me think that you aren't that familiar with "real" AJAX, so that's why I've got the next option:
Emit the Java YUI code directly from your code behind. Javascript is just more text that the server sends to the client and you can dynamically emit it just like any other part of your client script. ScriptManager can help here as far as getting it to the right spot on the page, but you could theoretically do it with just a place holder or literal control. Alternately, you could put most of the code in the markup and use <% %> to replace the parts that need to come from the server side. Either way, you need to write all the code to render your tree, then figure out the "Replaceable" bits and supply them from the server side code. BUT make sure that none of the info coming back is data that was entered by an end user otherwise you could end up with a Cross Site Scripting vulnerability.

Can you recommend alternative FileUpload control for asp.net-mvc?

Currently using System.Web.UI.WebControls.FileUpload wrapped in our own control.
We have licenses for Telerik. I wanted to know if anyone had experience with that or could suggest a better one?
Some criteria to be measured by
validation
peformance
multiple files
localisation (browse is difficult)
security
Personally, if you have the Telerik controls I would give them a shot. I've found that they are very helpful, and the user experience is good. Their upload control is quite nice.
I just posted about this in another question, but if you use this ActiveX control you will be able to process images quickly and efficiently. The component will actually resize the images on the client machine before sending them. This reduces unnecessary bandwidth and transfers multiple images at one time.
We extended the FileUploadControl to add some validation. We also wrote our own control that allows multiple files to be uploaded at once. We are currently evaluating both. Hopefully we decide on one, I would hate to have 2 different upload controls to maintain.
Check out Dean Brettle's NeatUpload. It's basically a custom HttpHandler that streams files to disk with loads of extra configurability. It's open source and Dean is an absolute star for supporting his users.
Check this one out: Html-5-Uploader
Drag-and-drop multiple files on your webpage!
Link doesn't always work so here it is again: http://www.igloolab.com/jquery-html5-uploader/
.
Controller: (modified from my original code, hope i don't forgot something, but it's pretty clear)
<HttpPost()> _
Public Function Upload(uploadedFile As System.Web.HttpPostedFileBase) As ActionResult
If uploadedFile IsNot Nothing Then
If uploadedFile.ContentLength > 0 Then
Dim mimeType As String = Nothing
'Upload
Dim PathFileName As String = System.IO.Path.GetFileName(uploadedFile.FileName)
Dim path = System.IO.Path.Combine(Server.MapPath("~/App_Data/Uploads"), PathFileName)
If Not System.IO.Directory.Exists(Path) Then
System.IO.Directory.CreateDirectory(Path)
End If
Dim firstLoop As Boolean = True
uploadedFile.SaveAs(path)
Next
End If
Return Nothing
End Function
This is the View (don't forget links to css and js ;))
<h1>
#SharedStrings.Upload</h1>
<h2>
#SharedStrings.UploadInformation</h2>
<div id="dropbox">
</div>
<div id="upload">
</div>
<script type="text/javascript">
$(function () {
var fileTemplate = "<div id=\"{{id}}\">"; fileTemplate += "<div class=\"progressbar\"></div>"; fileTemplate += "<div class=\"preview\"></div>"; fileTemplate += "<div class=\"filename\">{{filename}}</div>"; fileTemplate += "</div>"; function slugify(text) { text = text.replace(/[^-a-zA-Z0-9,&\s]+/ig, ''); text = text.replace(/-/gi, "_"); text = text.replace(/\s/gi, "-"); return text; }
$("#dropbox").html5Uploader({ onClientLoadStart: function (e, file) {
var upload = $("#upload"); if (upload.is(":hidden")) { upload.show(); }
upload.append(fileTemplate.replace(/{{id}}/g, slugify(file.name)).replace(/{{filename}}/g, file.name));
}, onClientLoad: function (e, file) { /*$("#" + slugify(file.name)).find(".preview").append("<img src=\"" + e.target.result + "\" alt=\"\">");*/ }, onServerLoadStart: function (e, file) { $("#" + slugify(file.name)).find(".progressbar").progressbar({ value: 0 }); }, onServerProgress: function (e, file) { if (e.lengthComputable) { var percentComplete = (e.loaded / e.total) * 100; $("#" + slugify(file.name)).find(".progressbar").progressbar({ value: percentComplete }); } }, onServerLoad: function (e, file) { $("#" + slugify(file.name)).find(".progressbar").progressbar({ value: 100 }); }
});
});
</script>
And my css
/*html 5 uploader*/
#dropbox
{
/*picture where people would drag-drop their files to*/
background-image:url(../Images/UploadToMedia.png);
height:128px;
margin-bottom:40px;
margin-left:auto;
margin-right:auto;
background-repeat:no-repeat;
margin-top:0;
width:128px;
}
You could try a flash-based solution that allows you to display whatever text, textboxes, buttons, or anything else as part of your own file upload control. These solutions typically put a 1x1 flash movie on the page that acts as a bridge between javascript and flash such that javascript can call flash's file upload box dynamically.
In a recent project, I used FancyUpload to do exactly that.

Categories