I am developing a custom tag for asp.net I want to read data from this tag database and return it as a class object and use it on aspx pages.
My code:
private T RenderControl<T>(Control control)
{
T test = (T)Convert.ChangeType(GetType(DataSource), typeof(T));
test = WebFramework.GetSingleData<T>(SQL, SQLParams.ToArray());
return test;
}
protected override void RenderContents(HtmlTextWriter output)
{
output.AddAttribute(HtmlTextWriterAttribute.Id, this.ID);
}
how can I do that? Example:
<a1:SingleOrDefault ID="test" runat="server" DataSource="MyProject.Models.Members" SQL="SELECT * FROM Members WHERE ID=1"></a1:SingleOrDefault>
<%= test.UserName %>
Thank you.
You could use JSON to convert the object to and from strings, and have your asp.net method work with strings rather than object. JSON can be interpreted in any almost language, server side and client side.
Example:
https://stackoverflow.com/a/2246724/8250558
Netwtonsoft is very popular: https://www.newtonsoft.com/json
Related
This code:
<asp:TextBox runat="server" MaxLength="<%=Settings.UsernameMaxLength %>" ID="Username"/>
Throws a parser error.
Is it possible to set properties in any way similar to this without using the code behind?
No, it is not possible. Syntax <%= some code here %> cannot be used with server-side controls. You can either go with <%# some code here %>, but only in case of data binding, or just set this property in code behind, say on Page_Load:
protected void Page_Load(object source, EventArgs e)
{
Username.MaxLength = Settings.UsernameMaxLength;
}
You may try this, which should set the MaxLength value upon rendering :
<%
Username.MaxLength = Settings.UsernameMaxLength;
%>
<asp:TextBox runat="server" ID="Username"/>
I think (not tried) you can also write :
<asp:TextBox runat="server" MaxLength="<%#Settings.UsernameMaxLength %>" ID="Username"/>
But you would then need to call Username.DataBind() somewhere in the codebehind.
I'm late to the party here, but here goes anyway...
You could build your own Expression Builder to handle this case. That would allow you to use syntax like this:
<asp:TextBox
runat="server"
MaxLength="<%$ MySettings: UsernameMaxLength %>"
ID="Username"/>
Note the $ sign.
To learn how to make you own Expression Builder, please go through this old but still relevant tutorial. Don't let the wall of text scare you off because in the end, making an expression builder is easy. It basically consists of deriving a class from System.Web.Compilation.ExpressionBuilder and overriding the GetCodeExpression method. Here is a very simple example (some parts of this code was borrowed from the linked tutorial):
public class SettingsExpressionBuilder : System.Web.Compilation.ExpressionBuilder
{
public override System.CodeDom.CodeExpression GetCodeExpression(System.Web.UI.BoundPropertyEntry entry, object parsedData, System.Web.Compilation.ExpressionBuilderContext context)
{
// here is where the magic happens that tells the compiler
// what to do with the expression it found.
// in this case we return a CodeMethodInvokeExpression that
// makes the compiler insert a call to our custom method
// 'GetValueFromKey'
CodeExpression[] inputParams = new CodeExpression[] {
new CodePrimitiveExpression(entry.Expression.Trim()),
new CodeTypeOfExpression(entry.DeclaringType),
new CodePrimitiveExpression(entry.PropertyInfo.Name)
};
return new CodeMethodInvokeExpression(
new CodeTypeReferenceExpression(
this.GetType()
),
"GetValueFromKey",
inputParams
);
}
public static object GetValueFromKey(string key, Type targetType, string propertyName)
{
// here is where you take the provided key and find the corresponding value to return.
// in this trivial sample, the key itself is returned.
return key;
}
}
In order to use it in your aspx page, you must also register it in web.config:
<configuration>
<system.web>
<compilation ...>
<expressionBuilders>
<add expressionPrefix="MySettings" type="SettingsExpressionBuilder"/>
</expressionBuilders>
</compilation>
</system.web>
</configuration>
This is just to show you that it's not difficult. But please review the tutorial I linked to in order to see an example of how to deal with the expected return type from your method depending on the property being assigned etc.
I'm trying to work with a class that has a child object, which has a string - and I'm trying to access this with in-line C# code on my aspx page.
More specifically, let's say I'm working with an object of 'Upload' class which has a Title property (String). An Upload object can also have a 'File' property (object). And each File object has a Url property (String).
I can access the Title like so:
<%# ((Upload)Container.DataItem)["Title"] %>
That works fine. But then how do I access a File's Url? Because the following does not work:
<%# ((File)((Upload)Container.DataItem)["File"]).Url %>
As you may be able to guess from the syntax, this is all within an asp repeater.
try this:
<%# ((Upload)Container.DataItem).File.Url %>
You get the container dataitem & cast it. Once you have the object, you can call it's properties & methods like any other object
you might try something like
<%# Bind("File.Url") %>
or
<%# DataBinder.Eval(Container.DataItem, "File.Url") %>
I am just giving you a sample, you can implmement the same on your own:-
First create a server side code to to return a URL of the File.
Then call that function from client side to get the URL of the title passed to the same.
Below is an example which returns the text with the suffix dots
Step 1 : Create server side code to return text with suffix dots
public string ReturnDotSuffix(string strValue, int iFontSize, int iWidth)
{
string strReturnValue = string.Empty;
try
{
CommonLib objCommonLib = new CommonLib();
strReturnValue = objCommonLib.SuffixDots(strValue, iFontSize, iWidth);
}
catch (Exception ex)
{
HandleException.ExceptionLogging(ex.Source, ex.Message, true);
}
return strReturnValue;
}
Step 2: Call this from Client Side.
Text='<%# ReturnDotSuffix((string)DataBinder.Eval(Container.DataItem, "MessageTitle"),8,170) %>'
The same can be done in your case.
For a site I'm developing I have two html buttons, not ASP because I do not want them to postback. For the submit button I am calling a javascript function that implements PageMethods to call a C# method from the codebehind. Here is the code for the buttons and the javascript.
<fieldset id="Fieldset">
<button onclick="SendForm();">Send</button>
<button onclick="CancelForm();">Cancel</button>
</fieldset>
<asp:ScriptManager ID="ScriptManager1" EnablePageMethods="true" EnablePartialRendering="true" runat="server" />
<script type="text/javascript">
function SendForm() {
var email = $get("txtEmail").value;
PageMethods.SendForm(email, OnSucceeded, OnFailed);
}
function OnSucceeded() {
$get("Fieldset").innerHTML = "<p>Thank you!</p>";
}
function OnFailed(error) {
alert(error.get_message());
}
</script>
The codebehind method shown here:
[WebMethod]
public static void SendForm(string email)
{
if (string.IsNullOrEmpty(email))
{
throw new Exception("You must supply an email address.");
}
else
{
if (IsValidEmailAddress(email))
{
bool[] desc = new bool[14];
bool[] local = new bool[14];
bool[] other = new bool[14];
for (int i = 1; i <= 14; i++)
{
desc[i] = ((CheckBox)Page.FindControl("chkDesc" + i.ToString())).Checked;
local[i] = ((CheckBox)Page.FindControl("chkLocal" + i.ToString())).Checked;
other[i] = ((CheckBox)Page.FindControl("chkOther" + i.ToString())).Checked;
/* Do stuff here */
}
}
else
{
throw new Exception("You must supply a valid email address.");
}
}
}
does not work unless it is declared as static. Declaring it as static blocks me from checking the checkboxes on the page because it generates a "An object reference is required for the non-static field, method, or property" error. So my problem can be fixed from either of two directions. A) Is there a way I can have this method work without declaring it as static? B) How do I check the checkboxes if the method is static.
It has to be static, no way around that; But you can access the Page like this
Page page = HttpContext.Current.Handler as Page;
and do FindControl on this page instance.
desc[i] = ((CheckBox)page.FindControl("chkDesc" + i.ToString())).Checked;
Page Methods are a special case of the legacy ASMX web service technology. They allow you to place the service in the codebehind class for the page, and keep you from needing a separate project for the service.
But they will never be able to access anything on the page itself. You'll have to do that from the client side, and pass the values of the check boxes to the service.
If you need to check the checkboxes, then you need to either use an UpdatePanel to do your AJAX stuff, or return something from your page method (ideally a string) and check the checkboxes based on what's returned in javascript on client.
I need to use the javascript functions to show and hide an element on my page, but calling it from within a C# method. Is this possible?
EDIT : I tried RegisterStartupScript (see below) but this did not hide the elements as I had hoped :
HidePopup("CompanyHQSetup", "$('#<%=DivDataProvider.ClientID %>').hide();$('#<%=modalOverlay.ClientID %>').hide();");
private void HidePopup(string Key, string jscript)
{
string str = "";
str += "<script language='javascript'>";
str += jscript;
str += "</script>";
RegisterStartupScript(Key, jscript);
}
EDIT : Got around this by using a hidden field boolean to determine whether or not to hide or show the elements
Yes, check out RegisterClientScriptBlock.
Here's a snippet taken from that link:
public void Page_Load(Object sender, EventArgs e)
{
// Define the name and type of the client script on the page.
String csName = "ButtonClickScript";
Type csType = this.GetType();
// Get a ClientScriptManager reference from the Page class.
ClientScriptManager cs = Page.ClientScript;
// Check to see if the client script is already registered.
if (!cs.IsClientScriptBlockRegistered(csType, csName))
{
StringBuilder csText = new StringBuilder();
csText.Append("<script type=\"text/javascript\"> function DoClick() {");
csText.Append("Form1.Message.value='Text from client script.'} </");
csText.Append("script>");
cs.RegisterClientScriptBlock(csType, csName, csText.ToString());
}
}
One is server side, the other is client side. They can pass variables to each other (Javascript to ASP would be via forms/querystring/cookies and ASP to JS done via response.writing variables), but they can't directly interact.
you can use page.RegisterClientScript method to do that go on the following url
http://msdn.microsoft.com/en-us/library/system.web.ui.page.registerclientscriptblock.aspx
and give it a try
Javascript is client side, c# is server side. You can't call javascript directly from C#. Take a look at Comet though, it will show you how you can push data from the HTTP server to the webpage.
I'm using ObjectForScripting property to interact with web page inside WebBrowser control and everything works fine except I can't figure out how to pass array of strings back to C#
HTML code
<input type="submit" onclick="window.external.save(Array('test', 'test2'))" />
Form
// Returns System.__ComObject
public void Save(object parameters)
{
}
// Throws an exception
public void Save(object[] parameters)
{
}
// Also throws an exception
public void Save(string[] parameters)
{
}
Rather than fight it; maybe approach the problem from another angle... could you (instead, either of):
delimit the data (with Array.join) and pass a single string, and split it (string.Split) in the C#
call Save multiple times, accepting a single string each time (Save(string s)), then call a final method to actually commit the changes
You can use an anonymous object instead of an array on the javascript side:
<input type="submit" onclick="window.external.save({first: 'test', second: 'test2'})" />
On the C# side (you need to use .NET 4.0 or more for the dynamic or use Type.InvokeMember if you are on an older version):
public void Save(dynamic parameters)
{
MessageBox.Show(parameters.first);
MessageBox.Show(parameters.second);
}
Not tested, but I think you can use reflection to discover the members.
Also look at this: http://dotnetacademy.blogspot.fr/2009/11/vbnetcnet-communication-with-javascript.html
function JS2VBArray( objJSArray )
{
var dictionary = new ActiveXObject( "Scripting.Dictionary" );
for ( var i = 0; i < objJSArray.length; i++ )
{
dictionary.add( i, objJSArray[ i ] );
}
return dictionary.Items();
}
Reference: http://msdn.microsoft.com/en-us/library/zsfww439(v=vs.80).aspx
<input type="submit" onclick="window.external.Save( JS2VBArray( ['test', 'test2'] ) )" />
This should go to the method.
public void Save(object[] parameters)
{
}
The string array is automatically passed as a comma-delimited string.
So this call:
window.external.save(Array('test', 'test2'));
Is received like so:
public void save(string fromjs)
{
string[] result = fromjs.Split(',');
}
It's a bit late for this, but typically when I need to pass objects or, in this case Arrays, I pass them as a JSON string.
var sArr = JSON.stringify(myArr);
window.external(sArr);
Then I have a JavaScriptSerializer on the other side that deserializes it back into an object / array.
Deserialize JSON with C#
To pass an array I found this to not be supported directly. I took the approach recommended by Marc Gravell to call multiple times but structured it in 3 methods instead, that are used in sequence: InitArgs, PushArg (multiple times), FinalArgs.
private System.Collections.Generics.Queue<string> _argsQ;
public void InitArgs()
{
_argsQ = new System.Collections.Generics.Queue<string>();
}
public void PushArg(string arg)
{
_argsQ.Enqueue(arg);
}
public void FinalArgs()
{
string[] parameters = _argsQ.ToArray();
// Save parameters
}
Now method calls can be used sequentially from html/js:
...onclick="var params = ['test', 'test2']; window.external.InitArgs(); for (var i=0; i<params.length; i++) window.external.PushArg(params[i]); window.external.FinalArgs();"...