Wednesday, January 29, 2014

Squiz Matrix Web Services SOAP API

The Squiz Matrix web services SOAP API is not well documented with code snippets or example and descriptions of exactly what sort of details need to go into which fields.
This is a problem if, for example, your management have negotiated an SLA which completely locks you out of your own server, but you need to upload a very large amount of documents to different locations. (The bulk upload tool only lets you put them in one place. The other tools require you to set up a file structure on the same server as Matrix is installed on.)
The following Java code snippet should help, showing how to upload a file with the Squiz Matrix SOAP API. It assumes you have generated the source code for the client using wsimport and added that web services client source to your project.
At present I have this working by making the intended 'parent' and the SOAP service asset in Matrix set to have 'public' write permissions, which is not such great security. But it works. Might investigate security more later.
Also, if you're not getting errors back, check the error log in Squiz.

private final edu.somewhere.www._web_services.soap.MatrixWebServices mwservices = new edu.somewhere.www._web_services.soap.MatrixWebServices();
 // private final edu.somewhere.www._web_services.soap.MatrixSOAPService servicess = new edu.somewhere.www._web_services.soap.MatrixSOAPService();
 MatrixSOAPService port = mwservices.getMatrixWebServicesPort(); 
 Holder<String> NewAssetIDOut = new Holder<String>();
 Holder<String> createMsgOut = new Holder<String>();
File file = new File("/path/to/my/TestWordFile.docx");
 byte[] pdfBytes = Files.readAllBytes(file.toPath());
 String fileContentsEncoded = Base64.encode(pdfBytes);
 
 List<AttributeInfo> attributeInfo = new ArrayList<AttributeInfo>();
 
 port.createAsset(
 // @WebParam(name = "TypeCode", targetNamespace = "")
// AssetType typeCode,
 AssetType.WORD_DOC,
 // @WebParam(name = "Name", targetNamespace = "")
// String name,
 "TestWordFile",
 // @WebParam(name = "ParentID", targetNamespace = "")
// String parentID,
 "84985",
 // @WebParam(name = "LinkType", targetNamespace = "")
// String linkType,
 "2",
 // @WebParam(name = "LinkValue", targetNamespace = "")
// String linkValue,
 "84985",
 // @WebParam(name = "SortOrder", targetNamespace = "")
// Integer sortOrder,
 0,
 // @WebParam(name = "IsDependant", targetNamespace = "")
// String isDependant,
 "TRUE",
 // @WebParam(name = "IsExclusive", targetNamespace = "")
// String isExclusive,
 "TRUE",
 // @WebParam(name = "FileName", targetNamespace = "")
// String fileName,
 "TestWordFile.docx",
 // @WebParam(name = "FileContentBase64", targetNamespace = "")
// String fileContentBase64,
 fileContentsEncoded,
 // @WebParam(name = "AttributeInfo", targetNamespace = "")
// List<AttributeInfo> attributeInfo,
 attributeInfo,
 // @WebParam(name = "NewAssetID", targetNamespace = "", mode = WebParam.Mode.OUT)
// Holder<String> newAssetID,
 NewAssetIDOut,
 // @WebParam(name = "CreateMessage", targetNamespace = "", mode = WebParam.Mode.OUT)
// Holder<String> createMessage);
 createMsgOut);
 
 System.out.println( "created??" + NewAssetIDOut.value + " ~~ " + createMsgOut.value);

Monday, November 7, 2011

Set TextBox.Text in FormView in Insert Mode from Code Behind

How to set text in a TextBox in InsertItemTemplate in a FormView with DefaultMode="Insert" from code behind.

You have an FormView with DefaultMode set to insert. You want people to come to this page/component to enter data. But you also want to populate it with data already existing from some other part of your database. This means you need to set it from code behind. Sounds straight forward. Seems to be something most people would want to do, so it ought to be intuitive.

Here are some things that don't work:

1. You try to access the TextBox by it's ID, like you normally would access an element on the page. (assuming it's id is 'TitleTextBox')
TitleTextBox.Text = ...
hang on it can't be found from code behind, so:

2. In the Page_Load load method, find the text field and set it's value with something like this:
TextBox DataTitle = (TextBox)FormView1.FindControl("TitleTextBox");
DataTitle.Text = "Sometext retrieved from the database or whatever."

Seems obvious - you load the page then set the text in the text field but this gives the error:

Operator '==' incompatible with operand types 'Guid?' and 'Object'

It seems that some sort of comparison is going on behind that code and there is a type missmatch. Maybe it's because the value for the TextBox hasn't been created yet, or the TextBox itself hasn't been created, or it's all null still or something.

3. In your LinqDataSource markup, you try:
<asp:Parameter Name="Title" ConvertEmptyStringToNull="true" DefaultValue="Some default value" />

But that doesn't put any value in the text field that the user can see. (You also try setting that value from code behind as long shot, but that's no good either) Not really what you would expect, but let's assume Microsoft's intention was to use the DefaultValue if the user hadn't put any text in. That's not the issue at hand so forget about it.

4. Maybe it's all because of the page loading life cycle. You try doing the same thing as above:
TextBox DataTitle = (TextBox)FormView1.FindControl("TitleTextBox");
DataTitle.Text = "Sometext retrieved from the database or whatever."
In the OnLoad(EventArgs e) event.
No joy.

5. I've lost track, but at some point I also tried:
LinqDataSource_Docs.InsertParameters["Title"].DefaultValue = "asdfasdfasdf"

THIS DOES WORK:

6. What really works is listening to the OnDataBound event of the FormView (so it is a lifecycle issue). It makes sense really. Why didn't you think of that first? It would have been nice if that answer was more common than the above suggestions in the forums/blogs, so here it is:

The markup is something like this:

<asp:FormView ID="FormView1" runat="server" DataSourceID="LinqDataSource_Docs" DefaultMode="Insert"
DataKeyNames="SomeDBId" CellPadding="6" OnDataBound="FormView1_DataBound">

And the code behind:

protected void FormView1_DataBound( object sender, EventArgs e )
{
String SomeDBId = Page.Request.QueryString["SomeDBId"];

var res = (from r in context.MY_DB_TBLs
where String.Equals(r.SomeDBId.ToString(), SomeDBId)
select r).Single();

TextBox DataTitle = (TextBox)FormView1.FindControl("TitleTextBox");
DataTitle.Text = res.Title; //or any text you like, not necessarily from the db query

}

Friday, September 16, 2011

A .epub ebook opened in Adobe Digital Editions, or in the Firefox ebook reader doesn't scroll through pages when you click the arrow. Instead it skips through chapters. This can be caused by using the 'float: right;' attribute in your CSS. Remove the float attribute and it works.

Monday, July 18, 2011

ASP.Net and IIS - Server Application Unavailable

Using IIS, Asp.Net and Visual Studio, I kept getting the very uninformative error for every .aspx page (even simple hello world ones):

Server Application Unavailable
The web application you are attempting to access on this web server is currently unavailable.

The server log was pointless, telling me nothing other than it was a 500 error.

It was serving html pages ok. I googled and googled, and tore my hair out and slept on it, and repeat... I ended up trying a few things, like:
- reinstalling IIS
- under Start->Administrative Tools->Internet Information Services (right click your site):
- making sure the home directory 'local path' is set to the right place
- ensure default.aspx is included as a default doc under the documents tab
- allowing IIS to control password under the security tab
- under 'Home Directory' tab making sure Execute Permissions is set to Scripts and Executables
- Setting the permissions on the default directory to allow IIS_WPG, including making sure that applied to all child files and folders.

What was useful was not the server log (under C:\WINDOWS\system32\LogFiles\) but the 'Event Viewer' (Start->Administrative Tools->Event Viewer). What you need to do to get a clue about what's going on is:
1. Try to load the aspx page that doesn't work.
2. In the event viewer, under 'Application', look at the most recent events that look likely candidates. Most likely the top ones.

This showed me a more useful error:

Failed to initialise the AppDomain:/LM/W3SVC/1/Root
Exception: System.Configuration.ConfigurationErrorsException

A bit of googling suggested reinstalling ASP.net and provided this convenient command for running at the DOS prompt:
%windir%\microsoft.net\framework\v2.0.50727\asp net_regiis -i -enable

When that didn't work, I changed the version to the ASP.net I had sent under Internet Information Services. So ultimately, what worked was running this command at the dos prompt:

C:\Documents and Settings\wdp921>%windir%\microsoft.net\framework\v4.0.30319\asp net_regiis -i -enable

There were too many blogs to reference them all here. While none of them alone provided the solution to the problem from start to finish they all led me to figure this out (at least I learnt a bit about IIS and ASP.net in the process) - so I don't claim credit for knowing the solution - I'm just putting it all here in one place in case it helps some one else, because one whole day is too much to waste.