Thứ Bảy, 19 tháng 9, 2009

WCF và tính tương thích với ASP.NET

Một sự khác biệt to lớn giữa các Web Services truyền thống ASMX và WCF Services là khả năng kích hoạt của chúng. Với WCF các services có thể được kích hoạt thông qua các giao thức ngoài HTTP như net.tcp, net.pipe hoặc WAS (Windows Activation Service). Trong khi ASMX service chỉ có thể được kích hoạt thông qua HTTP, và do đó nó liên kết chặt chẽ với ASP.NET HTTP pipeline. Điều này khiến cho các WCF services trở nên khá linh hoạt và động lập trong quá trình triển khai. Chúng có thể được deploy ở IIS, Windows Services hoặc các host tự tạo. Ngay cả khi WCF service được triển khai trên môi trường IIS, bên trong một ASP.NET application thì nó cũng không phụ thuộc vào các features của ASP.NET. Chúng ta dễ dàng nhận thấy rằng, các features trong ASP.NET như:

  • Authentication
  • Url/File authorization
  • Impersonation
  • Session state
  • Request cache
  • Globalization
  • Custom HttpModules

    Các features này thuộc về các thư viện HTTP:

  • System.Web.HttpApplication
  • System.Web.HttpContext

    Các features này sẽ không có khả năng sử dụng nếu như chúng ta không thiết lập ASP.NET Compatible Mode cho WCF. Khi đó, với HttpContext, đối tượng Current là luôn luôn null trong WCF. Để sử dụng các features này trong WCF, chúng ta cấu hình ASP.NET Compatible mode cho WCF. WCF cung cấp khả năng hỗ trợ ASMX thông qua các phương thức hosting khác nhau

    • Mixed Transports Mode
    • ASP.NET compatibility mode

    Để thiết lập ASP.NET Compatible Mode, chúng ta tham khảo hướng dẫn trên MSDN:

    http://msdn.microsoft.com/en-us/library/aa702682.aspx

    Reference: ASP.NET Compatibility Mode

  • Thứ Sáu, 11 tháng 9, 2009

    Xây dựng Report với Microsoft Reporting: MicrosoftReportViewer, Client Report Definition .rdlc

    Một trong những yêu cầu thường gặp khi xây dựng một phần mềm hoặc website ứng dụng đó là Report. Report có thể được thể hiện trên nhiều dạng khác nhau như danh sách, biểu đồ,…Đồng thời các Report phải được xuất ra các định dạng cơ bản như PDF, Excel, CVS,…Do đó nó cũng đòi hỏi yêu cầu về mặt thiết kế. Có nhiều công cụ lựa chọn để xây dựng Report như ActiveReport, Microsoft Report,…Tôi thích Microsoft Report vì nó mạng lại sự tiện dụng, sức mạnh và linh hoạt.

    Microsoft Reporting cung cấp sẵn cho chúng ta các template để thiết kế report như Crystal Report, Report Wizard, Report, đó là các client report definition files. Chúng ta sử dụng chúng để thiết kế, binding và tính toán cho report.

    A21319952F68E79E_536_0[1]

    Các client report definition này được hiển thị trên WinForms hoặc WebForms thông qua các container có sẵn như MicrosoftReportViewer với đầy đủ các công cụ cần thiết cho việc dàn trang, tìm kiếm, export…rất thuận tiện. Bộ thư việc của Microsoft Reporting cũng hết sức đơn giản bao gồm Microsoft.ReportViewer.Common.dll, Microsoft.ReportViewer.WinForms.dll nếu dùng WinForms và Microsoft.ReportViewer.WebForms.dll nếu dùng cho Web.

    A21319952F68E79E_536_1[1]

    Ngoài ra Microsoft Reporting cũng hỗ trợ rất nhiều nguồn data khác như như MS SQL, MS Access, Oracle, WebServives, XML, và đặc biệt quan trọng đó là Object Data Source.

      A21319952F68E79E_536_2[1]

    Một số tips khi sử dụng Microsoft Reporting.

    - Nested Object Binding: Thông thường chúng ta binding sử dụng các Properties của Object. Một vài trường hợp các Properties lại là một object khác. Khi đó chúng ta sử dụng Binding syntax: =Fields!Sales.Value.Customer.Name.

    public class CustomerInfo
    {
        public string Name {get; set;}
    }
     
    public class ProductSales
    {
        public CustomerInfo Customer {get; set;}
    }
     
    public class Product
    {
        public ProductSales Sales {get; set;}
    }







    - Collection Object Binding: Trong trường hợp chúng ta cần binding cho một Collections, ví dụ như một Order với nhiều Products. Khi đó chúng ta sử dụng Subreport để thiết kế report kiểu này. Chúng ta thiết kế 2 Report



    OrderReport: chứa một Subreport control. Control này bind lấy Product report và define một parameter như Id của Order để truyền đi khi load subreport



    ProductReport: Khai báo một parameter để nhận Order id khi load.



    Chúng ta implement SubreportProcessing Event để load subreport. Ở đó chúng ta nhận OrderId thông qua string orderId = e.Parameters[0].Values[0].ToString();



    và Add data source cho Subreport e.DataSources.Add(new ReportDataSource("SUBREPORT_DATA_SOURCENAME", GetDataSource(orderId )));



    - Ẩn hiện Column: Chúng ta sử dụng thuộc tính Visibility để control để quyết định việc ẩn hiện column phụ thuộc vào tham số



    A21319952F68E79E_536_3[1]



    - Export to PDF hoặc Excel programmatically:






    private void generateREPORT(string outputFormat)
            {
                Warning[] warnings = null;
                String[] streamids = null;
                String mimeType = null;
                String encoding = null;
                String extension = null;
                Byte[] bytes = null;
                if (outputFormat == "PDF")
                {
                    bytes = reportViewer.LocalReport.Render("PDF", null, out mimeType, out encoding, out extension, out streamids, out warnings);
                }
                else
                {
                    bytes = reportViewer.LocalReport.Render("Excel", null, out mimeType, out encoding, out extension, out streamids, out warnings);
                }
     
                Response.ContentType = mimeType;
                Response.Clear();
                if (outputFormat == "PDF")
                {
                    Response.AddHeader("Content-Disposition", "attachment; filename=RGP_TOTAL.pdf");
                }
                else
                {
                    Response.AddHeader("Content-Disposition", "attachment; filename=RGP_TOTAL.xls");
                }
                Response.BinaryWrite(bytes);
                Response.End();
            }


    - Landscape Report: mặc định report được xuất ra dưới dạng Portrait (Height lớn hơn (greater) Width). Để xuất report ra dạng Landscape, chúng ta chọn Reports –> Report Properties… Trong Layout tab, thiết lập Width > Height là ok



    - Auto Serial Numeber (No.): Thông thường các Report thường dưới dạng Grid với các Rows. Để thiết lập số thứ tự cho từng row (Row No.) chúng ta sử dụng function sau: =RowNumber(Nothing)



    Và rất nhiều các kỹ thuật khác.



    Chúc các bạn thành công khi sử dụng Microsoft Reporting

    Thứ Năm, 20 tháng 8, 2009

    InfoPath: Duplicate Attribute error

    “The formula contains one or more errors.
    Duplicate attribute”

    I got it when trying to add ,xsl as Data Connections to InfoPath then add new Rules to controls. Following this guide. It’s resolved the problem

    http://www.softobject.com/sites/Blog/Lists/Posts/Post.aspx?ID=4

    DUPLICATE ATTRIBUTE ERROR:

    This happens when a XSL file is added to the form as 2ndary data source.  The namespace in the XSL conflicts what's in Form's ns. 

    RESOLUTION:

    Do not add XSL as 2ndary data source.  Instead add it as form's Resource File.  Change your code that might be doing the XSLT transform to load the XSL manually.  This fixes it as charm!

    Work around code instead of havinf XSL as a secondary data source

    WITH XSL AS SECONDARY DATA SOURCE, YOU COULD HAVE DONE SOMETHING LIKE THIS:

    custom.HTMLDocument.body.innerHTML = thisXDocument.DOM.transformNode(thisXDocument.GetDOM("SummaryReport"));


    NOW SINCE THAT CAUSES NAMESPACE CONFUSION/CONFLICT, DO THE XSLT LIKE THIS:






    IXMLDOMDocument XSLTFileDOM = thisXDocument.CreateDOM(); 
    XSLTFileDOM.async = false; 
    XSLTFileDOM.validateOnParse = false; 
    XSLTFileDOM.load("SummaryReport.xslt"); 
    custom.HTMLDocument.body.innerHTML = thisXDocument.DOM.transformNode(XSLTFileDOM);



    -DANIEL





    It work for JScript. But C#, I don’t get the solution yet.



    Comments








    Quang Nguyen Ba - 8/21/2009 8:52:30 AM
    After asking someone over Internet. I found the solution for it. Following the guide from Jimmy http://www.infopathdev.com/forums/p/1641/46072.aspx, It work well. Here are complete codes for implementing transformation from from Resource Files






       1: XslCompiledTransform trans = new XslCompiledTransform();
       2: Stream xslTemplate = this.Template.OpenFileFromPackage("DNTN_Temp.xsl");
       3: XmlReader xslTemplateReader = XmlReader.Create(xslTemplate);
       4: trans.Load(xslTemplateReader);
       5: XmlTextWriter myWriter = new XmlTextWriter(resumeFile + "\\" + filename, null);
       6: trans.Transform(this.MainDataSource.CreateNavigator(), null, myWriter);
       7: myWriter.Close();

    Thứ Ba, 18 tháng 8, 2009

    WCF and ASP.NET Membership error: An error occurred when verifying security for the message

    System.ServiceModel.Security.MessageSecurityException: An unsecured or incorrect
    ly secured fault was received from the other party. See the inner FaultException
    for the fault code and detail. ---> System.ServiceModel.FaultException: An erro
    r occurred when verifying security for the message.
       --- End of inner exception stack trace ---

     

    I got this error message when deploy and use WCF with ASP.NET Membership over Internet. My WCF service use wsHttpBinding and Security mode = TransportWithMessageCredential. My machine for test are Windows 7, Visual Studio 2008 SP1, SQL Express 2005. I’ve spent more time to looking for solution. After that, It’s worked fine! Here are work around and solutions

    Open Event Viewer

    Following error was appeared:

    Failed to generate a user instance of SQL Server due to failure in retrieving the user's local application data path. Please make sure the user has a local user profile on the computer. The connection will be closed. [CLIENT: <local machine>]

    A21319952F68E79E_525_0[1]

    This is the root of problem.

    Solution:

    Add following account to SQL Server

    - IIS APPPOOL\DefaultAppPool

    - Local System

    - Local Services

    2. Open the Application Pool of your website used.

    A21319952F68E79E_525_1[1]

    You see: Identity: ApplicationPoolIdentity (Windows 7 IIS)

    A21319952F68E79E_525_2[1]

    3. Change the Identity to one of other account then iisreset

    A21319952F68E79E_525_3[1]

    Hope this help!

    Thứ Năm, 13 tháng 8, 2009

    Export InfoPath form to Word 2003 document sử dụng XSLT, XPath và C#

    Trong bài viết trước, Export InfoPath form to Word 2003 document sử dụng XSLT và XPath tôi đã đã hướng dẫn các bạn cách Export InfoPath form sử dụng JScript code. Bài này hướng dẫn các bạn một cách khác, sử dụng C# Code.

    Chúng ta cũng thực hiện các bước tương tự như bài trước. Tuy nhiên lựa chọn Programming language ở đây là C#. Chúng ta sử dụng đoạn code sau cho Button Event

       1: //Retrieve the xsl to use to transform the InfoPath form into document.xml
       2: DataSource ds = this.DataSources["XMLToWordML"];
       3: XslCompiledTransform trans = new XslCompiledTransform();
       4: trans.Load(ds.CreateNavigator());
       5:  
       6: //create the output stream
       7: XmlTextWriter myWriter = new XmlTextWriter
       8:    ("result.xml", null);
       9:  
      10: // Transform the InfoPath form and save the XML into the stream for the part
      11: trans.Transform(this.MainDataSource.CreateNavigator(), null, myWriter);
      12: myWriter.Close() ; 


    Các bạn sẽ thấy, kết quả thực hiện không khác so với sử dụng JScript. Bởi vì khi can thiệp vào các Event, Action trong InfoPath, chúng ta không thể sử dụng đồng thời cả JScript và C# cùng một lúc. Do đó, các bạn cần phải lựa chọn Programming Language cho InfoPath. Đối với các bài toàn phức tạp, chúng ta nên sử dụng C#, ngược lại các yêu cầu đơn giản chúng ta sử dụng JScript là một thuận lợi

    Thứ Tư, 12 tháng 8, 2009

    InfoPath: Custom save form using JScript

    Đôi khi chúng ta cần save InfoPath file dưới một tên và folder đã được định sẵn. Bài viết này hướng dẫn các ban làm điều đó.

    1. Mở InfoPath để thiết kế 1 form với một textbox control

    2. Vào Tools –> Form Options và chọn “Save using custom code” và click on “Edit…” button

       1: function XDocument::OnSaveRequest(eventObj)
       2: {
       3:     try
       4:      {
       5:         //XDocument.UI.SetSaveAsDialogLocation("\\my\form\directory")
       6:         XDocument.UI.SetSaveAsDialogLocation("C:\\")
       7:         var strFileName = XDocument.DOM.selectSingleNode("/my:myFields/my:field1").text + ".xml"; 
       8:         XDocument.UI.SetSaveAsDialogFileName(strFileName);
       9:         eventObj.IsCancelled = eventObj.PerformSaveOperation();
      10:         eventObj.ReturnStatus = true;
      11:      } 
      12:      catch(e)
      13:      {
      14:         XDocument.UI.Alert("Error at OnSaveRequest: " + e.message);
      15:         eventObj.ReturnStatus = false;
      16:      }  
      17: }

    3. Save Infopath form. Chúng ta có thể sẵn sàng test.


    Comments




    Dũng Nguyễn - 11/3/2009 9:21:05 AM
    Anh Quang ơi cái này đâu có hỗ trợ cho browser forms đâu. Anh có đoạn code nào về save file infopath hỗ trợ browser forms không ạ.


    Bư béo ™ - 2/23/2010 10:55:02 AM
    anh ơi em ko hiểu, em mà sử dụng code thì nó ko hỗ trợ browser form:(. anh ơi có cách nào giúp em với ko ạ?


    Quang Nguyen Ba - 2/27/2010 4:42:29 PM
    Với browser form thì thường chúng ta sẽ save vào SharePoint List. Bài viết này áp dụng cho Offline form. Mục tiêu là giải quyết vấn đề tự động Save với các form offline mà không cần chọn Save Target folder. Như vậy việc nhập dữ liệu hàng loạt sẽ nhanh hơn.
    Với code này, anh chưa thử với Browser Form, tuy nhiên anh tinh là sẽ sử dụng được. Tuy nhiên khác một điều là nó sẽ save lên thư mục trên Server deploy InfoPath Service


    Quang Nguyen Ba - 2/27/2010 4:44:06 PM
    Để dùng được code với Browser Form thì chúng ta cần deploy InfoPath dưới dạng Trusted. Nếu deploy lên MOSS 2007 thì deployment phải được quản lý bởi Central Administration

    InfoPath Auto Submit to Local Folder using JScript

    Khi sử dụng InfoPath, đôi khi chúng ta có nhu cầu tự động submit với filename là một field nào đó trên InfoPath form, hoặc là được đặt sẵn. Để thực hiện được điều này chúng ta có thể sử dụng C# code hoặc JScript. Bài viết này hướng dẫn các bạn thực hiện điều đó. Bài viết đề cập đến các kỹ thuật sau:

    - Tự động submit infopath form sử dụng JScript code.

    - Tự động save filename sử dụng một text field trên form

    - Kiểm tra folder đã tồn tại hay chưa trước khi submit

    - Sau khi submit mở luôn một form mới để nhập

    1. Trước hết chúng ta kiểm tra Programming Language default của InfoPath form khi thiết kế sử dụng InfoPath thiết lập cho JScript

    A21319952F68E79E_511_0[1]

    2. Chúng ta thiết kế một form đơn giản bao gồm một textbox và một button

    A21319952F68E79E_511_1[1]

    3. Click chuột vào Submit button và chọn Action là Submit. Sau đó click on Submit Option… button.

    4. Trong Submit Options dialog box, chọn “Allow users to submit this form” –> Chọn “Perform custom action using Code”. Trong “After submit” option, chọn “Create a new, blank form”. Sau đó click on “Edit Code…” button.

    A21319952F68E79E_511_2[1]

    5. Chúng ta sử dụng JScript Code như sau để submit

       1: function XDocument::OnSubmitRequest(eventObj)
       2: {    
       3:     //Get the filename
       4:     var strFileName = XDocument.DOM.selectSingleNode("/my:myFields/my:field1").text + ".xml"; 
       5:     var xmlDoc = XDocument.DOM.xml;  
       6:     //create FSO Object
       7:     var objFSO = new ActiveXObject("Scripting.FileSystemObject");  
       8:     //Check the folder exist
       9:     if(!objFSO.FolderExists("C:\\InfoPath"))
      10:   {
      11:   //Create folder
      12:    objFSO.CreateFolder("C:\\InfoPath");
      13:   }            
      14:     //Create file
      15:     var tempFile = objFSO.CreateTextFile("C:\\InfoPath\\" + strFileName , true);  
      16:     //Save
      17:     tempFile.Write(xmlDoc);     
      18:     eventObj.ReturnStatus = true;
      19: }

    6. Đảm bảo form được full trust


    A21319952F68E79E_511_3[1] 


    7. Giờ các bạn sẵn sàng test form.


    Note: Nếu chúng ta muốn lưu data sau khi submit vào thư mực hiện thời của .xsn file, chúng ta sử dụng câu lệnh:


    var folder = fso.GetFolder(".");


    để get current folder của .xsn file.


    var folderPath = fso.GetFolder(".").path;


    để lấy đường dẫn của thư mục hiện thời