You are currently browsing the tag archive for the ‘C#’ tag.

How to: DISTINCT, SUM, COUNT the DataTable for a given XML?

 

Advertisements

Problem statement:
Callbacks not working in WebBrowser control.

Possible resolution:
Check to see if your code is COM Callable? Because for WebBroswer.ObjectForScripting to work COMVisible attribute must be added and set to true.

Something like following on the top of the class declaration:

[System.Runtime.InteropServices.ComVisibleAttribute(true)]

From MSDN:

Use this property to enable communication between a Web page hosted by the WebBrowser control and the application that contains the WebBrowser control. This property lets you integrate dynamic HTML (DHTML) code with your client application code. The object specified for this property is available to Web page script as the window.external object, which is a built-in DOM object provided for host access.

From MSDN:

using System;
using System.Windows.Forms;
using System.Security.Permissions;

[PermissionSet(SecurityAction.Demand, Name="FullTrust")]
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class Form1 : Form
{
private WebBrowser webBrowser1 = new WebBrowser();
private Button button1 = new Button();

[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form1());
}

public Form1()
{
button1.Text = "call script code from client code";
button1.Dock = DockStyle.Top;
button1.Click += new EventHandler(button1_Click);
webBrowser1.Dock = DockStyle.Fill;
Controls.Add(webBrowser1);
Controls.Add(button1);
Load += new EventHandler(Form1_Load);
}

private void Form1_Load(object sender, EventArgs e)
{
webBrowser1.AllowWebBrowserDrop = false;
webBrowser1.IsWebBrowserContextMenuEnabled = false;
webBrowser1.WebBrowserShortcutsEnabled = false;
webBrowser1.ObjectForScripting = this;
// Uncomment the following line when you are finished debugging.
//webBrowser1.ScriptErrorsSuppressed = true;

webBrowser1.DocumentText =
"
" +
"function test(message) { alert(message); }" +
"
" +
"";
}

public void Test(String message)
{
MessageBox.Show(message, "client code");
}

private void button1_Click(object sender, EventArgs e)
{
webBrowser1.Document.InvokeScript("test",
new String[] { "called from client code" });
}
}

Happy ‘callback’ing! (0:

A few notes for those trying to question, how to run WebBrowser in a Console application?

  • WebBrowser control is primarily intended for Forms based app. 
  • Console app is not on STA(Single Threaded Apartment – which offers a message-based communication between OS and application for dealing with multiple objects running concurrently) by default; which means no message pumping, which means no events are going to be fired – so don’t be shockingly surprised, must if you go that way!

If must, you choose Console, then following may be the options:

  • You can use a WebClient, or HttpWebRequest to request a page and parse response manually.
  • You can write your own message pump by adding a GetMessage/DispatchMessage in a while loop; and then you add the switch cases for the Message that you are looking for. Its goes something like:

while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
  • Add a Form(with WebBrowser control) to your console app and do Application.Run(YourForm), for it to dispatch the events.
  • Show the Form in another thread with its own message pump; probably a hidden form.

[STAThread]
static void Main(string[] args)
{
System.Threading.Thread thdBrowser = new System.Threading.Thread(RunFormInParallel);
thdBrowser.SetApartmentState(System.Threading.ApartmentState.STA);
thdBrowser.Start();

Console.ReadLine();
}

private static void RunFormInParallel()
{
Form form1 = new Form();//new form

WebBrowser webBrowser = new WebBrowser();//create a browser
webBrowser.Dock = DockStyle.Fill;
webBrowser.Url = new Uri("http://www.bing.com");

form1.Controls.Add(webBrowser);//add to form

Application.Run(form1);//run
}

Enjoy coding!

There is a new type, a contextual keyword, called dynamic in C# v4.0; getting to much of a popularity among advanced programming.It is used to call operations of dynamic languages (DLR).

To put it simply, binding is the association of a symbol within a program with an address in memory. The term “binding”, in this case refers to the process of resolving types, members, and operations.

  • Static binding happens at compile time, where a compiler identifies, resolves, and throws exception if necessary, at compile time.
  • Dynamic binding refers to identification, resolution, and throwing of exception if any, during runtime.

Dynamic binding in useful in cases where you know that a certain member, function, or operation would be available at run time. But compiler doesn’t know about that; the compiler would not throw any exceptions as well because it would just “trust you”, because you used dynamic keyword.

“A dynamic type tells the compiler to relax. We expect the runtime type of d to have
a Quack method. We just can’t prove it statically.” – (C# in a Nutshell Chap-4 Pg161)

dynamic dynTest = new Test();
dynTest.AnotherTest(1);

dynamic means that all expressions using dynTest is bound at execution time, rather than at compile-time, and thus makes it behave dynamically.

dynamic versus var keyword

A lot of times dynamic is confused with the var keyword; and to prove that statement, following is such an example that creates quite a confusion.

//CODE 1
var varTest = new Test();
varTest.AnotherTest(1);
//CODE 2
dynamic dynTest = new Test();
dynTest.AnotherTest(1);

Here, in CODE 1, var means the static type is inferred – in this case it’s same as

Test varTest = new Test();

var is static typed – the compiler actually knows the type All the binding is still done entirely statically.

dynamic, in CODE 2, means that all expressions using dynTest is bound at execution time, rather than at compile-time, and thus makes it behave dynamically. Compiler won’t check whether the AnotherTest() method exists – the behavior is determined at execution/run time.

Note that, somewhat on a tangent, if the object implements IDynamicMetaObjectProvider it could decide what to do with the call at execution time, responding to any method call – in other words, there doesn’t have to be a “real” method called AnotherTest() at all.

This type of binding is also called “Custom Binding”; Custom binding occurs when a dynamic object implements IDynamicMetaObjectProvider (IDMOP). I’ll write more about custom binding sometime.

If you’d like to read more, here is a worth viewing, if you are short of reading time, article C# 4.0 – Dynamic Language Runtime by Microsoft’s Bruno Terkaly with excellent visuals.

Happy dynamic’s! (0:

A lot of times I have come across this question on several forums; and to not avail the google, the question is being asked again and again. If at any point someone might feel they should google, and if google ever planned to re-rank my site to a higher level – then I’d guarantee that following code would work.

I did a reply to a post here on StackOverflow; though my code is pretty old – out of my project code – but as they say, old is gold, so here it goes.

Usage:

XMLValidator val = new XMLValidator();
if (!val.IsValidXml(File.ReadAllText(@"d:\Test2.xml"), @"D:\Test2.xsd"))
MessageBox.Show(val.Errors);

Code:

public class CXmlValidator
{
private int nErrors = 0;
private string strErrorMsg = string.Empty;
public string Errors { get { return strErrorMsg; } }
public void ValidationHandler(object sender, ValidationEventArgs args)
{
nErrors++;
strErrorMsg = strErrorMsg + args.Message + "\r\n";
}

public bool IsValidXml(string strXml/*xml in text*/, string strXsdLocation /*Xsd location*/)
{
bool bStatus = false;
try
{
// Declare local objects
XmlTextReader xtrReader = new XmlTextReader(strXsdLocation);
XmlSchemaCollection xcSchemaCollection = new XmlSchemaCollection();
xcSchemaCollection.Add(null/*add your namespace string*/, xtrReader);//Add multiple schemas if you want.

XmlValidatingReader vrValidator = new XmlValidatingReader(strXml, XmlNodeType.Document, null);
vrValidator.Schemas.Add(xcSchemaCollection);

// Add validation event handler
vrValidator.ValidationType = ValidationType.Schema;
vrValidator.ValidationEventHandler += new ValidationEventHandler(ValidationHandler);

//Actual validation, read conforming the schema.
while (vrValidator.Read()) ;

vrValidator.Close();//Cleanup

//Exception if error.
if (nErrors > 0) { throw new Exception(strErrorMsg); }
else { bStatus = true; }//Success
}
catch (Exception error) { bStatus = false; }

return bStatus;
}
}

Here is a kb that demonstrates the use of several types of validation. This site provides Xml/Schema validation online.

Following is the code using non deprecated methods.

public bool IsValidXmlEx(string strXmlLocation, string strXsdLocation)
{
bool bStatus = false;
try
{
// Declare local objects
XmlReaderSettings rs = new XmlReaderSettings();
rs.ValidationType = ValidationType.Schema;
rs.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation | XmlSchemaValidationFlags.ReportValidationWarnings;
rs.ValidationEventHandler += new ValidationEventHandler(rs_ValidationEventHandler);
rs.Schemas.Add(null, XmlReader.Create(strXsdLocation));

using (XmlReader xmlValidatingReader = XmlReader.Create(strXmlLocation, rs))
{ while (xmlValidatingReader.Read()) { } }

////Exception if error.
if (nErrors > 0) { throw new Exception(strErrorMsg); }
else { bStatus = true; }//Success
}
catch (Exception error) { bStatus = false; }

return bStatus;
}

void rs_ValidationEventHandler(object sender, ValidationEventArgs e)
{
if (e.Severity == XmlSeverityType.Warning) strErrorMsg += "WARNING: " + Environment.NewLine;
else strErrorMsg += "ERROR: " + Environment.NewLine;
nErrors++;
strErrorMsg = strErrorMsg + e.Exception.Message + "\r\n";
}

Happy validation!

Crystal Report Viewer “This field name is not known.” Error!

I was using Crystal Reports Viewer control in my ASP.NET web application; when some of the reports, out of thousands, didn’t seem to work. Although, those reports worked fine in Crystal Reports Designer IDE; but when run in my web app, I was thrown this this field name is not known error. So, had to dig in and fix the thing up on production.

Problem symptoms:

  • When trying to view a report in Report Viewer the report prompts for parameters and then gets stuck with an error message box titled “Crystal Report Viewer” and the error is “This field name is not known.”
  • Some reports are showing error that “This field name is not known.” – problem in report formula?

  • Same report, I can view with CR Designer IDE but CR Viewer (web based) throws the error “This field name is not known.”.

Refer to this discussion for more information. And the problem that I was having, see following figure.

Dint find anything useful on Business Objects’s search-unfriendly web forum. Then I came across this Crystal Reports Fix (HTTP location, or FTP location); following two issues made me try this fix:

 Which, un/fortunately didn’t work either!

Resolution:
What actually helped, atlast, is this post here on MSDN forum, in guessing” the possible reasons of what might have been going wrong.

Following actually worked:

string strLocation = connectionInfo.DatabaseName + ".dbo." + table.Location.Substring(table.Location.LastIndexOf(".") + 1);

table.Location = strLocation;

So, after applying the new ApplyLogOnInfo(), you will need to set the table location explicitly – again – so that, it would remove old values and apply anew.

Following generic method might help:

private void SetDBLogonToTables(CrystalDecisions.Shared.ConnectionInfo connectionInfo, CrystalDecisions.CrystalReports.Engine.ReportDocument reportDocument)
{
CrystalDecisions.CrystalReports.Engine.Tables tables = reportDocument.Database.Tables;

foreach (CrystalDecisions.CrystalReports.Engine.Table table in tables)
{
CrystalDecisions.Shared.TableLogOnInfo tableLogonInfo = table.LogOnInfo;

tableLogonInfo.ConnectionInfo = connectionInfo;
table.ApplyLogOnInfo(tableLogonInfo);

//Following, did the trick!
try
{
string strLocation = connectionInfo.DatabaseName + ".dbo." + table.Location.Substring(table.Location.LastIndexOf(".") + 1);

table.Location = strLocation;
}
catch (Exception ex)
{//Catch
}
}
}

Will Rickards has provided a nice example, accessing multiple databases changing the datasource location of the report during runtime.

Someone pretty pissed off, wrote:

“…and no thanks to anyone involved in the development of Crystal Reports. There is no good excuse for the dozens of problems that Crystal Reports has and continues to have.
…so it won’t be long before the Crystal company (currently Business Objects?) is sueing Microsoft for putting them out of business by creating a superior product.”

David Hilton in the end, adds to the post that I referred to earlier:

We don’t have a good process for publishing the release notes for Crystal Reports to the SDN yet. We are discussing this issue with the program managers to have them released regularly.

Happy crystallizing the reports! (0:

Issue: Active Directory not showing all users

There is an active directory related issue, which does not list all users available in the AD. This occurs because of the fact that if DirectorySearcher.PageSize is not set then the server defaults that property to 1000.

Set .PageSize property of your searcher object to 1000, sets the page size and LDAP handles the pagination internally automatically. And Michael Freidgeim is a great guy!

Happy roaming around the active directory (0:

How to merge multiple Excel workbooks into one?

Only if you want something like: Merge(@”E:\Test”, @”E:\FinalDestination.xls”);

Use following code.

private void Merge(string strSourceFolder, string strDestinationFile)
{
try
{
//1. Validate folder,
//2. Instantiate excel object
//3. Loop through the files
//4. Add sheets
//5. Save and enjoy!

object missing = System.Reflection.Missing.Value;
Microsoft.Office.Interop.Excel.ApplicationClass ExcelApp = new Microsoft.Office.Interop.Excel.ApplicationClass();
ExcelApp.Visible = false;

//Create destination object
Microsoft.Office.Interop.Excel.Workbook objBookDest = ExcelApp.Workbooks.Add(missing);


foreach (string filename in Directory.GetFiles(strSourceFolder))
{
if (File.Exists(filename))
{
//create an object
Microsoft.Office.Interop.Excel.Workbook objBookSource = ExcelApp.Workbooks._Open
(filename, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing
, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);


//Browse through all files.
foreach (Microsoft.Office.Interop.Excel.Worksheet sheet in objBookSource.Worksheets)
{
sheet.Copy(Type.Missing, objBookDest.Worksheets[objBookSource.Worksheets.Count]);
}

objBookSource.Close(Type.Missing, Type.Missing, Type.Missing);
objBookSource = null;

}
}
objBookDest.SaveAs(strDestinationFile, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
objBookDest.Close(Type.Missing, Type.Missing, Type.Missing);

objBookDest = null;
ExcelApp = null;


}
catch (System.Exception e)
{
//Catch
}
}

Btw, this was in response to a post on StackOverflow.

Microsoft Enterprise Library: Microsoft Application Blocks (Data Access)

I have been using Microsoft’s Data Access Application Block for windows forms; and this time I plan to use ‘em in my ASP.NET project. I tend to like application block framework, mostly because for me it saves a lot of time and it provides a bug free code.

I mean seldom you feel a need to write your own data layer unless otherwise is explicitly required/demanded. So I get more time to think about my applications’ logic.

Just for those who have no idea what a data access application block is, following would reveal the before-and-after scenarios; and how it can push you into the “flow” that we seek during our development phase.

1. Code – Without application block
Following the code that create, and opens a connection, make a query, load the data into result and then binds it to the grid.

// Open connection
SqlConnection theConnection = new SqlConnection("Server=(local);Database=TestDB;Integrated Security=True;");
theConnection.Open();

//Create stored procedure command object
SqlCommand theCommand = new SqlCommand("GetEmployeesByDepartment", theConnection);
theCommand.CommandType = CommandType.StoredProcedure;

//Add parameter for stored procedure
theCommand.Parameters.Add("@DepartmentID", SqlDbType.Int);
theCommand.Parameters["@DepartmentID"].Value = 9;

//create DataAdapter and DataSet objects
SqlDataAdapter theAdapter = new SqlDataAdapter(theCommand);
DataSet dsResult = new DataSet("Result");

//fill dataset
theAdapter.Fill(dsResult);

//databind the grid
DataGrid1.DataSource = dsResult;
DataGrid1.DataBind();

//clean up
theConnection.Close();

2. Code – With application block
Following does the same as above but with lesser code.

//Make connection
string theConnection = "Server=(local);Database=TestDB;Integrated Security=True;";

//Execute
DataSet dsResult = SqlHelper.ExecuteDataset(theConnection, CommandType.StoredProcedure,"GetEmployeesByDepartment", new SqlParameter("@DepartmentID", 9) );

//Assign and bind
dgvResult.DataSource = dsResult;

dgvResult.DataBind();

Data Access Application Block
The Data Access Application Block simplifies many common data access tasks such as reading data for display, passing data through application layers, and submitting changed data back to the database system. It includes support for both stored procedures and in-line SQL, and provides access to the most often used features of ADO.NET in simple-to-use classes.

Key Scenarios
The Data Access Application Block is suitable if you encounter any of the following
situations:

  • Using a DataReader or DataSet to retrieve multiple rows of data.
  • Executing a command and retrieve the output parameters or a single-value item.
  • Performing multiple operations within a transaction.
  • Retrieving XML data from a SQL Server.
  • Updating a database with data contained in a DataSet object.
  • Adding or extend implementations of database providers.

When to Use
The Data Access Application Block is ideal for addressing the following requirements:

  • You need simplicity and convenience while helping developers use the functionality provided by ADO.NET with best practices.
  • You need to reduce the requirement for boilerplate code to perform standard data access tasks.
  • You need to maintain consistent data access practices, both within an application and across the enterprise.
  • You need to make it easy to change the target database type through configuration, and reduce the amount of code that developers must write when they port applications to different types of databases.
  • You need to relieve developers from learning different programming models for different types of databases.

Considerations
The following considerations apply to using the Data Access Application Block:

  • The Data Access Application Block is a complement to ADO.NET; it is not a replacement.
  • If your application must retrieve data in a specialized way, or take advantage of features specific to a particular database, consider using ADO.NET directly.

Download; you may download the msi from here.

Reference to assembly; add reference to the Microsoft.ApplicationBlocks.Data.dll assembly and start using Microsoft.ApplicationBlocks.Data.

MSDN; Also go through the Data Access Application Block documentation at Microsofts website.

Btw, v5.0 is still(as of now); under construction.

Microsoft Application Architecture Guide – Second Edition 2009 (p489)

The maximum report processing jobs limit configured by your system administrator has been reached:

Fortunately a post threw me to a reference provided by Ludek Uher and Trevor Dubinsky; senior engineers with Technical Customer Assurance, SAP Business Objects. Though this seems to be an old problem hanging around Crystal Reports since version 10, I noticed that this was just acknowledge and workaround-ed couple of months ago(17th June, 2009) from now.

Click here to see the work around PDF; here is Microsoft Word based older version.

%d bloggers like this: