Friday, 11 January 2013

Extract OLE Objects from MS Access to Disk


Problem Statement - 
Fetch the documents(images, .pdf, .doc etc.) from the MS Access(OLE Object) and store it on disk.
Initially, i thought it would be quite easy. Being a C# developer, i quickly began with the VS2010. I  already had the MS Access DB which has a table with several columns. But my focus was on only few such as
  • ID - Primary Key - Int
  • Name - text
  • Structure - OLEObject (Contains images)
  • Certificate - OLEObject (Contains PDFs)
Within half an hour, i had all the information in the DataTable with OLEObject as byte[]. Now, the point was how would i know the format of the images in the Structure columns. Because if we view the Access, it simply displays the type of document ( Bitmap Image for .bmp, Microsoft Word Document for .doc etc.), no file or extension name. Moreover , for other types, it just display the text as "Package".
To start with, i assumed that System.Drawing.Image
might have the detailed information  once i convert the byte[] to MemoryStream and assign this to Image Object.
byte[] bPhoto;//Assign it with data.

int id;//Primary key - Used as the name for the image here.

/*We have also hard-coded the extension as .png for now.*/

 using (MemoryStream stream = new MemoryStream(bPhoto)){
       System.Drawing.Image tempImage = System.Drawing.Image.FromStream(stream);
       string FName = tempPathPhoto + Path.DirectorySeparatorChar + Convert.ToString(id) + ".png";
       tempImage.Save(FName);
  }
As soon as i executed the code to debug and analyze the tempImage data, it threw an exception on this line -
System.Drawing.Image tempImage = System.Drawing.Image.FromStream(stream);
and the exception was - Parameter is not valid.  
I googled it and found various links to get rid of that. But, those solutions didn't worked for me. So i tried a couple of other ways to write the files such as - 

FileStream file = new FileStream(tempPathPhoto + Path.DirectorySeparatorChar + Convert.ToString(id) + ".GIF", FileMode.Create, System.IO.FileAccess.Write);
file.Write(bPhoto, 0, bPhoto.Length);
file.Close();
and
File.WriteAllBytes(tempPathPhoto + Path.DirectorySeparatorChar + Convert.ToString(id) + extension, bPhoto);
Using the above specified ways, i was able to write the file on my disk. Hmmm.. That wasn't tough.    But these files didn't open as expected. The Image viewer displayed it as the crashed image and the PDF were displayed as corrupted as well. I was on Zero again. 

After googling with some new keywords, i landed on this page. I found more than 50 blogs and sites pointing to this link. The first thing I (and most probably whoever visited) noticed was that the site is out of support. But don't worry, the download link and the project works just fine. Run the Access page and fill all the fields accordingly and viola!! It extracted the files perfectly. Nice work Mr. Leban.

All my .bmp,.pdf files were there in the correct place. But wait!! What about the other file format. Those who had banged their head on wall might have noticed that when we insert the .bmp file, the field value says "Bitmap File Format" but when we insert other type of images, it display "package". When you try to extract the data with "package" name, the code runs smoothly but the files were created with ".pak" extension and that too didn't opened up correctly. So, Is the issue with the images uploaded?? - I don't think so as the Access form displays the images perfectly.  So, what is the issue??

Lets see the code. I went through almost all the lines of my interest especially the fGetContentsStream(). Going through the  "package" case, Mr. Leban mentioned all the bits he has added to the "lPos" variable  so as to get the correct data from the file. I don't know if this is the case only with me because thousands of people have used his code and if there is some issue there, someone must have pointed it out. Anyways, i analyzed some of the files that were getting displayed as "package" and found that before extracting the file information( such as File Name, Full Path etc.), the lPos value should be set to "84".
So i reinitialize the lPos just before the following line of code in fGetContentsStream() "Package" case - 

'Reset the lPos
lPos = 84

' Package original File Name
Do While bCurValue <> 0
    bCurValue = arrayOLE(lPos)
    FileNamePackage = FileNamePackage & Chr(bCurValue)
    lPos = lPos + 1
Loop
This is it. Run the form again and it will extract all the OLE Object named as "package". All hail Mr. Leban.

One more issue, i faced was with MS Office 2007 Docs. For ex- .doc file would be extracted fine but the .docx file be displayed as corrupted when you try to open it.
I tried some alterations and after a while of head-banging, i got this code working - 

Case "Word.Do"
' MS Word document

sExt = "doc"
If sClassName = "Word.Document.12" Then
FileExtension = "docx"
sStreamName = "Package" ' This is important
Else: FileExtension = "doc"
sStreamName = "WordDocument"
End If
And
Select Case sStreamName

Case "CONTENTS", "Package" ' Package added by Shadab
' Contents stream in Root Storage
' Call our function in the StrStorage DLL
    lLen = GetContentsStream(arrayOLE(0), UBound(arrayOLE) - lOffSet, sStreamName)

Case "Ole10Native"
' "Ole10Native" stream in sub storage named "Embedding 1" Of Root Storage
' Call our function in the StrStorage DLL
    lLen = GetContentsStreamChild(arrayOLE(0), UBound(arrayOLE) - lOffSet, sStreamName)

Case Else
' Need to fix this to allow for other stream names other than Office Docs.
' Extract Office doc
    lLen = ExtractOfficeDocument(arrayOLE(0), UBound(arrayOLE) - lOffSet, sStreamName)

End Select

I was able to extract .docx files now. Unfortunately, the same didn't work for the other files such as .xlsx (Excel2007). Not that much important as of now but I am still looking for the workaround for this problem. Any suggestions???

Thanks
S. Shafique
Fokat RnD Team Member

Monday, 7 January 2013

Host WCF on both HTTP & HTTPS

Hi,
We have created a WCF service for one of our project a while ago. Yesterday, for some reasons, the system administrator enabled the SSL on IIS. And our WCF service stopped working with the exception -

Endpoints using 'UriTemplate' cannot be used with 'System.ServiceModel.Description.WebScriptEnablingBehavior'.


As usual, my suspect was the UriTemplate initially. I cross checked my service but everything was fine. When i gooogled this error, the symptoms(i.e. using UriTemplate with WebGet and enableWebScript tag in config file) for the error were not there in service.
So i concluded that the culprit must be the SSL. I requested them to disable the SSL for a moment and Viola.. It started working again perfectly. so my focus shifted from code error to binding with SSL. I came through this post . Just for the sake of my own records and quick reference, pasted the code here as well, as  posted by  

<system.serviceModel>  
  <services>
    <service behaviorConfiguration="MyServiceBehavior" name="JK.MyService">      
      <endpoint address="" behaviorConfiguration="WebBehavior" binding="webHttpBinding" bindingConfiguration="webBinding" contract="JK.IMyService">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
      <endpoint address="" behaviorConfiguration="WebBehavior" binding="webHttpBinding" bindingConfiguration="webBindingHTTPS" contract="JK.IMyService">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
      <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />      
    </service>
  </services>    
  <behaviors>    
    <serviceBehaviors>      
      <behavior name="MyServiceBehavior">
        <serviceMetadata httpGetEnabled="True" httpsGetEnabled="true"/>
        <serviceDebug includeExceptionDetailInFaults="true" />
      </behavior>      
    </serviceBehaviors>    
    <endpointBehaviors>
      <behavior name="WebBehavior">
        <webHttp/>
      </behavior>
    </endpointBehaviors>    
  </behaviors>  
  <bindings>
    <webHttpBinding>
      <binding name="webBinding">
        <security mode="None">
          <transport clientCredentialType="None" />
        </security>
      </binding>
      <binding name="webBindingHTTPS">
        <security mode="Transport">
          <transport clientCredentialType="None" />
        </security>
      </binding>
    </webHttpBinding>
  </bindings>  
</system.serviceModel>

Apply the respective changes to your config accordingly and it works like charm. A big thanks to JayaKrishna.

Thanks
S. Shafique
Fokat RnD Team Member

Friday, 28 December 2012

Code First Approach For New Database

I was trying my hands on Entity-framework. As i was completely blank on this areas, I Googled about it and found some interesting links. This link helped me to have some conceptual understanding( Though i have to read it again a couple of times to get what it actually means. )

Later, to have some practical know-how, i followed this link. I found the link on this page very useful to begin with. There are various approaches to work on. Lets begin with Code First Approach for New Database -

The page is itself the best place to follow the approach. No doubt , you won't find better details here. So whats the use of this page. I got stuck in a couple of places. (as was with my first HelloWorld program  )
  1. I was using VS2010.The tutorial do not mention to place the connection string anywhere in the code. Obviously, it was not necessary to mention it but as i ran the program with exactly the same code, this exception popped up  -
    "The provider did not return a ProviderManifestToken string."
     When i checked the details of this exception, it found that it was an error related to database connection. But where should i mention these details. First, i mentioned a connection string in the app.config.
     <add name="BlogContext" 
    connectionString="Data Source=ZZZ;User ID=XXX;Password=XXX;Initial Catalog=YYY;Persist Security Info=true" 
    providerName="System.Data.SqlClient" />

     Then i update the BlogContext class by supplying it a constructor. 
     public BlogContext()
                : base("Name=BlogContext")
            {
    
            }

    The next time i ran it. It created the tables in the DB defined in the connection string. 
  2. When we change the POCO Classes in order to change the DB. We won't get the error till the code actually hits the DB. The error indicates us to use Data Migration tool to get the changes to the Database.
    To do this, Open the Package Manager Console(Tools->Library Package Manager->Package Manager Console), And Fire the command -
      Enable-Migration
    Tip- To use intellisense, hit [tab], not [Ctrl+Space]. It's console not editor.
    Then run the command below after you have changed the classes -
    Add-Migration AddChange
    Here, AddChange  is the Name of migration which could be anything(Name it properly so that you can easily recall the changes). A file is created with the migration name where you can see all the upgrade/downgrade related changes.
    Finally, run the Update-Database command to migrate the Changes to DB.
      
Thanks,
S. Shafique
Fok at RnD Team member

Wednesday, 26 December 2012

Using view as both View and Partial View


A couple of days back, we were in a situation where we have to display the same view (say "AddTicket") as
  • View in some cases(new tab) and
  • as partial view in other(in modal pop-up).
To accomplish that, there might be various approaches but two thoughts came in my mind-
  • Create separate view and partial view (which was discarded as we would have to write the same HTML layout twice).
  • Create a Partial View and use it as View wherever and whenever required.

To do that, first create a partial view with Layout property set to "null".(Obviously)

public ActionResult AddTicket()
        {
            /*
             We are using the same as View and Partial View here.
             */
            if (Request.IsAjaxRequest()|| ControllerContext.IsChildAction)
            {
                return PartialView("PartialViewName");
            }
            else
            {

               //Set the Layout for the partial view
                return View("PartialViewName","~/Views/Shared/_Layout.cshtml");
            }
        }

Needless to say, i am expecting there should be a better approach than this. Looking forward for the suggestions.

Thanks,
S. Shafique
Fok at RnD Team member

Friday, 21 December 2012

Create ComplexType If Stored procedure returns multiple Select statements in Entity Framework



Guys, Today during our daily development we faced another big problem.
We are using Ef4(Entity Framework) in our project using EDM(Entity Data Model) approach .
The problem is that we have one stored procedure which returns two select statement in the output
For ex – Select * from emp;
                Select * from library;
1.In function import the complex type will only hold one type of object like either emp or library , so we can’t able to show result of the stored procedure .
2.If we manually execute Stored procedure query  then also it will return the result of first select.
Like this ->
var query = _cxt.ExecuteStoreQuery<TestModel>("exec testselect");

And the drawback is that EF4 is not supporting multiple select in edm.
It is available in EF5 by nugget.

Now we have come up with the result.
Here we go.

1.First we have downloaded extension for Entity Framework

2. Include that project in your project.
3.Create new class file and Create a partial class in the same name of your Entities Class
In my case
       public partial class TestDatabaseEntities : ObjectContext

Now suppose my stored procedure return as an output like this.

       Select * from tblState;
       Select * from tblCountry;
Include that extension in that file.

4.As there is two type of object returning from SP tblState and tblCountry.
So create two private readonly variable of same type.
Like this

       private static readonly Materializer<tblState> s_StateMaterializer = new Materializer<tblState>(r =>
            new tblState
            {
                id = r.Field<int>("id"),
                StateName = r.Field<string>("StateName"),
            });

        private static readonly Materializer<tblCountry> s_CountryMaterializer = new Materializer<tblCountry>(r =>
            new tblCountry
            {
                countryId = r.Field<int>("countryId"),
                countryName = r.Field<string>("countryName"),
                isActive = r.Field<bool>("isActive")

            });

5.Now Comes the Method which will return multiple record Set.

public void GetMultiple()
        {
            DbCommand command = this.CreateStoreCommand("TestSelect", CommandType.StoredProcedure); //Create the command which will call the sp.
            List<tblCountry> country;
            List<tblState> state;

            using (command.Connection.CreateConnectionScope()) //Opening Connetion
            using (DbDataReader reader = command.ExecuteReader()) // Getting Data on Data reader
            {
                state = s_StateMaterializer
                        .Materialize(reader)
                        .Bind(this.tblStates)
                        .ToList<tblState>();  //Extracting the State from the output

                if (reader.NextResult())
                {
                    country = s_CountryMaterializer
                        .Materialize(reader)
                        .Bind(this.tblCountries)
                        .ToList<tblCountry>();  //Extracting the Country from the output
                }
               
            }

        }
In my case it is void type you can change acc to your requirement.
That’s all now call this method and see the output.

Thanks
Morpheus
Fokat RND Team Member

Thursday, 20 December 2012

Custom or User define Attribute in MVC


Hello frnd ,
I am writing this blog for a type of problem which we face during development in mvc-3 or mvc4 .
For a registered user we have to check Session  in every action of every controller ,which is very tedious.
Like this ,
                If (YourSessionObject != null)
{
                //your code goes here.
}

It is very tedious.
So Here is the solution.
You all know about Mvc Attributes. So we can make one attribute which will check our session object and if found null then return back to login page.
So the question is where to write this class, The class will be written in App_Start .
The class should implement ActionFilterAttribute.

In that class you have to over ride OnActionExecuting method.
Here is the code below

public class SessionExpireFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            HttpContext ctx = HttpContext.Current;

            // check if session is supported
            CurrentCustomer objCurrentCustomer = new CurrentCustomer(); //This is session object
            objCurrentCustomer = ((CurrentCustomer)SessionStore.GetSessionValue(SessionStore.Customer));
            if (objCurrentCustomer == null)
            {
                // check if a new session id was generated
                filterContext.Result = new RedirectResult("~/Users/Login"); // if null then return back to login page .
                return;
            }

            base.OnActionExecuting(filterContext);
        }
    }
That’s all just include App_Start in controller and just add [SessionExpireFilter] attribute in your action method.
This will check session in every action .

Kendo Tab Control

Using Tab control has always been an easy task to accomplish. But due to lack of sufficient documentation(IMO) of Kendo Tabstrip for MVC, it took me a while to get what i was looking for.

To begin with -
You can follow the basic documentation link of Kendo.
For everything else that was not exactly there in doc -
  1. Display image with absolute URL -  Simply use
    .ImageUrl("http://Absolute/path/of/the/image.")
  2. Display content from Partial View - I found a couple of ways for that. 
    1- .Content(@<text> @(Html.Partial("_PartialView1"))</text>);
     
    2- .Content(Html.Partial("_PartialView2").ToHtmlString());
    
    3- .Content(@<text> @(Html.Action("View3"))</text>);
  3. Change the animation from "expand" to "toggle" - 
  4. .Animation(animation =>
        {
            animation.Enable(true);
            animation.Open(config =>
            {
                config.Duration(AnimationDuration.Fast);
                config.Fade(FadeDirection.In);
            });
        })
    
  5.  Difference in LoadContentFrom  and Content in case someone is confused. 
     
Thanks,
S. Shafique
Fok at RnD Team member