Last Thursday, I finally got a nagging problem resolved – display Chinese characters successfully in PDF created dynamically by iTextSharp API. The lack of postings and articles on the subject has prompted me to wrap up my workings in a short article and published to codeproject.com and here is the link to that article http://www.codeproject.com/KB/aspnet/ChineseinPDFiTextSharp.aspx
Display double-byte character in PDF created by iTextSharp
Written by stevey on May 16th, 2011Manipulate master page from content page
Written by stevey on April 14th, 2011I have a admin.master master page that is shared by several content pages. On the master page, I have a set of side-bar menus that get loaded dynamically from a xml file via a WebuserControl, this part of codes look like this:
<div id="LeftSideMenu" style="height:100%;">
<uc3:SideMenuXml ID="mnuCalendar" runat="server" MenuName="Calendar" /> <uc3:SideMenuXml ID="mnuUser" runat="server" MenuName="User" />
</div>
In the SideMenuXml.ascx, codes behind load xml content properly based on the MenuName which corresponds to a segment in the xml file that looks like this:
<Sidebar>
<Calendar>
<Name>School Calendar</Name>
<Url>student/SchoolCalendar.aspx</Url>
<Description>View school calendar</Description>
<DisplayOrder>1</DisplayOrder>
<Roles>Public</Roles>
</Calendar>
</Sidebar>
This has been working great, but sometimes I want a different set of side menus loaded into admin.master based on the purpose of the content page. Today, I learned that this can be accomplished by these steps:
- Create a public property in the master page, named “PageType” or whatever
- To access this property of master page, I needed to add this attribute to the content page, <%@ MasterType VirtualPath=”~/Admin.master” %>
- Then on the Page_Init event of my content page, I set this property to an enum value I wanted: protected void Page_Init(object sender, EventArgs e) { Master.PageType = MasterPageTypes.Contest;
} - Then on the admin.master I added this line of server-client-mixed code:
<div id="LeftSideMenu" style="height:100%;">
<% if (PageType== MasterPageTypes.Contest) {%>
<uc3:SideMenuXml ID="mnuContest" runat="server" MenuName="Contest" />
<% } %>
With that, I accomplished the goal of showing certain Contest related side menu for those content pages that set the PageType property of admin.master master page.
To sum it up, public property of master page is not accessible from its content page until you add this MasterType directive to the content page that uses the master: <%@ MasterType VirtualPath=”~/Admin.master” %>
Retrieve dropdown list’s selected text in jQuery
Written by stevey on April 11th, 2011Often times there is need to access a DropDown list control’s selected text from client side; for example, this server control has a server id “ddlSubject”, how would you access its selected text using jquery? I thought this was trivial, using $(“[id$=’ddlSubject’]”).text() would do, as $(“[id$=’ddlSubject’]”).val() I knew would give me the selected value. Wrong!!. As matter of fact, $(“[id$=’ddlSubject’]”).text() returned all the option texts, not just the selected text.
Well, as it turned out, what’s really working is to use $(“[id$=’ddlSubject’] option:selected”).text();
Hello 您好!
Written by stevey on March 9th, 2011Welcome to blog.yangsoft.com. Today I switched my blogs from BlogEngine.Net to WordPress and felt placid to see everything falling in places just fine. I’ve had no trouble installing BlogEngine.Net to my site’s sub-domain but I had huge trouble getting it to work; I was no afraid of troubles as long as I was able to locate where the problem came from; but Godaddy, where my site is hosted, kept getting me the “500 error” and their tech support was unable to help me solve that puzzle. Even though I am a professional .Net developer and completely new to php, which is what WorldPress is written in, I find this WorldPress blog engine more robust, powerful and easier to use. So here I am WorldPressing!
P.S. all the blogs that were dated earlier than today, March 9, 2011, were actually imported from BlogEngine.Net database that I still kept.
Consume WCF service from .Net 1.1
Written by stevey on January 2nd, 2011I have struggled for the past week not being able to consume a ASMX service exposed through a WCF service app that was created on .Net 4.0 and Entity Framework. The key to make a WCF service consumable by legacy .Net app was to expose the service as an old fashion ASMX, through adding a XmlSerializerFormat attribute while building the ServiceContract interface, as shown in this sample:
[ServiceContract, XmlSerializerFormat]
public interface IService1
{
[OperationContract]
string GetData(int value);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
}
The second key step was to make sure the web.config of the WCF service project would use “basicHttpBinding” and set endpoint address to “basic” type. When I first started out, many cited the reference from MSDN at http://msdn.microsoft.com/en-us/library/ms751433.aspx; I followed the example, and still got the “Underneath connection had been closed” error. Today, I came across another posting at http://social.msdn.microsoft.com/forums/en-US/wcf/thread/1f8c7fe9-784c-4beb-8d0f-060bf8bfc24f and that had liberated me from wondering why this damn thing not working – well, the web.config example in the MSDN article had an empty string in the address field while this social.msdn positing had a “basic” in the enpoint address; I tried that and it worked this time! Thanks Jay R. Wren who answered a user’s question at social.msdn.com.
Here was the endpoint configuration that worked on my case:
<service name=”WcfService1.Service1″ behaviorConfiguration=”AsmxBehavior”>
<endpoint address=”basic” binding=”basicHttpBinding” contract=”WcfService1.IService1″></endpoint>
The entire web.config file that is in the WCF app project that will generate the ASMX service to be consumed by .Net 1.1 client is as below:
<?xml version=”1.0″?>
<configuration>
<system.web>
<compilation debug=”true” targetFramework=”4.0″ />
</system.web>
<system.serviceModel>
<services>
<service name=”WcfService1.Service1″ behaviorConfiguration=”AsmxBehavior”>
<endpoint address=”basic” binding=”basicHttpBinding” contract=”WcfService1.IService1″></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name=”AsmxBehavior”>
<!– To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment –>
<serviceMetadata httpGetEnabled=”true”/>
<!– To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information –>
<serviceDebug includeExceptionDetailInFaults=”false”/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled=”true” />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests=”true”/>
</system.webServer>
</configuration>
Use Session in Generic Handler file (.ashx)
Written by stevey on December 12th, 2010Using Generic Handler or .ashx file instead of heavyset web form (.aspx) is a lighter-weight and faster way to handle certain types of Http request, such as rendering an large image, spit out text files, etc. I recently used it in one web project that needed to setup a Http listener to process incoming requests and not doing any Html rendering.
By default, an .ashx file (Generic Handler template from VS2010) code behind automatically added these namespaces only:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
Then when I tried to store a session_id from incoming Http request’s querystring in the Session object of HttpContext.Current, and it failed. As it turned out, in order to access Session object, I needed to add a SessionState namespace, System.web.SessionState; and then implement the IRequiresSessionState interface. the beginning of the .ashx code behind now looked like this:
public class ServeRequest : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
//codes to handle Http request
}
}
Find out where your website is blocked
Written by stevey on October 14th, 2010Today, I was extremely frustrated that two of the websites I developed and hosted at Godaddy.com were not accessible inside China. Did a trace route (run tracert.exe from command line) from the client’s PC inside China and found that the site was blocked at an IP address that is registered under CNC Group in Beijing China. Then I did more research on Google and discovered that website blocking is quite common in China, and some people pointed me to use a web Ping tool to find out how a Http request to you r website page travels through the Internet. The tool vividly showing the locations across the globe a Ping command travels, and it tabulated the information, including the Name of hub (location), result, IP, and average RRT.
To access this tool, go to http://www.just-ping.com and enter your website address.
Some others recommended going through VPN to access websites without restriction. One commenter recommended using http://www.vpninchina.com/; it costs 3 Euro a month, or 36 Euro a year to use the VPN software.
Mysterious connection error in WCF web service call
Written by stevey on October 14th, 2010While working on a WCF Service call to return an e-commerce order object to a web client , I sometimes got this puzzling error inside client code:
“The underlying connection was closed: The connection was closed unexpectedly.”
At the beginning, I thought this must be something to do with Entity connection or some SQL to Entity operations inside the data tier that was built on ASP.Net Entity Framework; but there was nothing to be found there.
Then I searched and visited many web postings, and most of them pointed to configuration problem with WCF service model’s endpoint settings. I even followed some postings and made the corresponding changes; but this dreaded error still lingered. I was about to give up before I realized that the WCF service call was working fine before I added couple of enumerated class members to the DataContract class that is to return. Here was the class that was built into my WCF services layer and to be returned to client when the service method “GetOrder” was called:
[DataContract] public class EcommOrder : SalesOrder
{
[DataMember] public int EcommOrderID { get; set; }
[DataMember] public int EcommOrderTypeID { get; set; }
// … more data members
}
//web service method call
public EcommOrder GetOrder(int orerid)
{
EcommOrder returned=new EcommOrder();
//retrieve order from data tier (EF) and populate the object
return returned;
}
On the client side where the service was invoked, the serializable object EcommOrder was fetched good and sound. Then I added this enum member to the EcommOrder class inside the Service tier:
[DataContract] public enum OrderTypes
{
[EnumMember]
StudentOrder=1,
[EnumMember]
CorporateOrder=2,
//and so on
} and EcommOrder now looks like :
[DataContract] public class EcommOrder : SalesOrder
{
[DataMember] public int EcommOrderID { get; set; }
[DataMember] public int EcommOrderTypeID { get; set; }
[DataMember] public OrderTypes EcommOrderType;
// … more data members
}
Then I went back to the client code and call the same service call to return the modified EcommOrder object: Oops, now I got that dreaded and misleading error:
“The underlying connection was closed: The connection was closed unexpectedly.”
To confirm the Enum was the cause, I went back and took out the EcommOrderType enumerated member, then re-called the service, yes, the error again went away.
How wacky was that?
Return JSON data synchronously using jQuery.ajax()
Written by stevey on September 10th, 2010Normally, I would have used .getJSON(remotePageUrl,data,function(json){
//process JSON data here, for example
//if (json.length>0)
{
alert(json[0].Name);
}
});
to get a JSON object returned from the remotePageUrl that processes my request asynchronously and send back a JSON format string like ‘{“Name”:”steve”,”ID”: “1234”}’
But today, I found out that the .getJSON() cannot be set to process data request synchronously. In order to send data to remotePageUrl and return result synchronously (reason for this was because I had a jQuery dialog to be populated with data returned from this call before the dialog was displayed; first I used $.getJSON(), the dialog showed up before the data was processed on server side and returned), I needed to use $.ajax(). Here is the ajax call that actually worked to serve my purpose well:
var dataUrl = “<%=root%>/ajax/AsyncEventDataHandler.aspx”;
var userid; var eventTypeId; var userEventDesc=”;
var responseText = $.ajax({
url: dataUrl,
type: ‘GET’,
dataType: ‘JSON’,
//dataType: ‘text’,
contentType: ‘application/json’,
data: “UserCalendarID=” + userCalendarID,
async: false,
success: function (response) {
var data=$.parseJSON(response);
userid = data.UserID;
eventTypeId = data.EventTypeID;
userEventDesc = data.UserEventDesc;
},
error: function (msg) { alert(“error: ” + msg); }
}).responseText;
Here the response inside the function() is the same as $.ajax(….).responseText, and it should have a proper JSON string format or the jQuery.parseJSON() function will fail. The correct format example: ‘{“UserID”:”1211″,”EventTypeID”:”1″,”UserEventDesc”:”meeting”}’. I tried to put single quote around the field name and it did not go through $.parseJSON(). For example, this will not be parsed: “{‘UserID': ‘1211’,’EventTypeID':’1′,’UserEventDesc':’meeting’}”.
For that I attributed to this article at jQuery api site at: http://api.jquery.com/jQuery.parseJSON/. Otherwise, I would probably wasted more time in figuring out why the parsing was failing.
Create and consume WCF Service from scratch
Written by stevey on September 1st, 2010Today, I read an article on Codeproject.com by Mike Liu and he gave a very detail illustration on how to create and consume a WCF service from scratch, without using any of those pre-existing WCF templates in VS2010. It was very refreshing and no wonder the article ended up in last month’s new author winner list
These were the steps I went through to create and consume a HelloWorld WCF service following Mike’s instruction:
- Selected a Blank solution from VS2010 -> C#/Other Project Types/Visual Studio Solutions
- Added a Class library (named HelloWorldService) to the solution (Solution file resided in the root folder and named HelloWorld. When the class lib was created, it automatically created a folder called HelloWorldService)
- added a reference to System.ServiceModel.dll to the class lib
- Added an Interface class called IHelloWorld.cs to the project and defined ServiceContract and OperationContract, like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace Yangsoft.Training.WCF
{ [ServiceContract]
public interface IHelloWorldService
{
[OperationContract]
String GetMessage(String name);}
} - renamed the class1.cs to HelloWorldService.cs and implemented the interface, like this:class HelloWorldService : IHelloWorldService
{public String GetMessage(String name)
{return “Hello World from ” + name;
}
} - Service was created and now it needed to be hosted on a website. To accomplish that, added a new website, named HostDevServer to the HelloWorld solution and made this website use static port: 8080. The website was added as blank website, did not have any string attached and no need to change default web location, File System.
- Added a reference to the website project to pick up HelloWorldService class library
- Then I opened the web.config; before I added any WCF related stuff, the web.config only had a <system.web> entry. Followed the instruction given in the article, added system.webserver and system.serviceModel sections, now the web.config looks like this:<configuration>
<system.web>
<compilation debug=”false” targetFramework=”4.0″ />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests=”true”></modules>
</system.webServer>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name=”MyServiceTypeBehaviors”>
<serviceMetadata httpGetEnabled=”true”/>
<serviceDebug includeExceptionDetailInFaults=”false”/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name=”Yangsoft.Training.WCF.HelloWorldService” behaviorConfiguration=”MyServiceTypeBehaviors”>
<endpoint address=”” binding=”wsHttpBinding” contract=”Yangsoft.Training.WCF.IHelloWorldService” ></endpoint>
<endpoint address=”mex” binding=”mexHttpBinding” contract=”IMetadataExchange” ></endpoint>
</service>
</services>
</system.serviceModel>
</configuration> - Now added a .svc file the hardcore way: just added a plain text file called HelloWorldService.svc and added the entry and the only entry to the text file:<%@ ServiceHost Service=”Yangsoft.Training.WCF.HelloWorldService” %>This basically created a website to host the HelloWorlService that a client consume.
- Added a Console project, named HelloWorldClient to the solution, no app.config, no other class except the default Program.cs class in the project at this point.
- The final piece of major work was to run svcutil.exe to generate the service proxy on this client. This was accomplished all in command line mode:
- backed out to DOS mode, navigated to the folder where HelloWorldClient console app resided
- run this command from the folder:“c:\program files\microsoft sdks\windows\v6.0a\bin\svcutil.exe” http://localhost:8080/HostDevServer/HelloWorldService.svc?wsdl after this was run, it generated two files in the HelloWorldClient folder: HelloWorldService.svc and output.config (here I did not follow exactly the instruction given by the Author). Before this was run, I had run the HostDevServer without debuging and checked and made sure the service was created correctly.
- Returned to the VS2010 solution explorer and go to Project/Show All Files and included the two files created by the svcutil.exe tool in the Console project. Renamed the output.config to app.config and made sure added a reference to the project for System.ServiceModel.
- Open the Program.cs and added these lines in the Main static method:{
HelloWorldServiceClient client = new HelloWorldServiceClient();
Console.WriteLine(client.GetMessage(“Steve Yang”));
} - set the start up project to be the console and hit Ctrl+F5 to run the program in non-debug mode, and the output of the program should be a line saying “Hello World from Steve Yang” or whatevever I programmed in the GetMessage(String name) method in the HelloWorldService.cs in the HelloWorldService class library.
In real world of VS2010, I did not have to do all these as there are pre-written WCF templates that I could just drag-and-drop into the solution and automatically populate the web.config and app.config. But I agreed with the author, going through these tedious steps had helped me understand WCF service dearly.