Contents tagged with Controls
Speech synthesis and recognition were both introduced in .NET 3.0. They both live in System.Speech.dll. In the past, I already talked about speech synthesis in the context of ASP.NET Web Form applications, this time, I’m going to talk about speech recognition.
.NET has in fact two APIs for that:
System.Speech, which comes with the core framework;
Microsoft.Speech, offering a somewhat similar API, but requiring a separate download: Microsoft Speech Platform Software Development Kit.
I am going to demonstrate a technique that makes use of HTML5 features, namely, Data URIs and the getUserMedia API and also ASP.NET Client Callbacks, which, if you have been following my blog, should know that I am a big fan of.
First, because we have two APIs that we can use, let’s start by creating an abstract base provider class:
It basically features one method, RecognizeFromWav, which takes a physical path and returns a SpeechRecognitionResult (code coming next). For completeness, it also implements the Dispose Pattern, because some provider may require it.
In a moment we will be creating implementations for the built-in .NET provider as well as Microsoft Speech Platform.
The SpeechRecognition property refers to our Web Forms control, inheriting from HtmlGenericControl, which is the one that knows how to instantiate one provider or the other:
The control exposes some custom properties:
Culture: an optional culture name, such as “pt-PT” or “en-US”; if not specified, it defaults to the current culture in the server machine;
Mode: one of the two providers: Desktop (for System.Speech) or Server (for Microsoft.Speech, of Microsoft Speech Platform);
SampleRate: a sample rate, by default, it is 44100;
Grammars: an optional collection of additional grammar files, with extension .grxml (Speech Recognition Grammar Specification), to add to the engine;
Choices: an optional collection of choices to recognize, if we want to restrict the scope, such as “yes”/”no”, “red”/”green”, etc.
The mode enumeration looks like this:
The SpeechRecognition control also has an event, SpeechRecognized, which allows overriding the detected phrases. Its argument is this simple class that follows the regular .NET event pattern:
Which in turn holds a SpeechRecognitionResult:
This class receives the phrase that the speech recognition engine understood plus an array of additional alternatives, in descending order.
You need to add an assembly-level attribute, WebResourceAttribute, possibly in AssemblyInfo.cs, of course, replacing MyNamespace for your assembly’s default namespace:
This attribute registers a script file with some content-type so that it can be included in a page by the RegisterClientScriptResource method.
And here is it:
OK, let’s move on the the provider implementations; first, Desktop:
What this provider does is simply receive the location of a .WAV file and feed it to SpeechRecognitionEngine, together with some parameters of SpeechRecognition (Culture, AudioRate, Grammars and Choices)
Finally, the code for the Server (Microsoft Speech Platform Software Development Kit) version:
As you can see, it is very similar to the Desktop one. Keep in mind, however, that for this provider to work you will have to download the Microsoft Speech Platform SDK, the Microsoft Speech Platform Runtime and at least one language from the Language Pack.
Here is a sample markup declaration:
If you want to add specific choices, add the Choices attribute to the control declaration and separate the values by commas:
Or add a grammar file:
By the way, grammars are not so difficult to create, you can find a good documentation in MSDN: http://msdn.microsoft.com/en-us/library/ee800145.aspx.
And that’s it. You start recognition by calling startRecording(), get results in onSpeechRecognized() (or any other function set in the OnClientSpeechRecognized property) and stop recording with stopRecording(). The values passed to onSpeechRecognized() are those that may have been filtered by the server-side SpeechRecognized event handler.
A final word of advisory: because generated sound files may become very large, do keep the recordings as short as possible.
Of course, this offers several different possibilities, I am looking forward to hearing them from you!
A long, long time ago, I wrote a NHibernateDataSource control. Back then, it was based in the first LINQ provider for NHibernate, and a long has happened since. Now, I decided to give it another go!
Historically, in ASP.NET, a data control should inherit from DataSourceControl, like ObjectDataSource, LinqDataSource, EntityDataSource, SqlDataSource, etc, and should expose collections for parameters for each of the supported operations (select, update, delete and insert). Since ASP.NET 4, however, a new base class came along: QueryableDataSource. This class is an implementation of IQueryableDataSource, which allows using QueryExtender, also introduced in version 4, to filter and sort the results of a data source that uses LINQ.
I wanted my control to be able to use QueryExtender, but I also wanted to be able to give it an HQL query. It should also be capable of inserting, updating and deleting entities.
So, here’s what I came up with, first, the NHibernateDataSource class:
You can see that it exposes some events:
- Configure: gives developers a chance to build (or return an existing) Configuration instance, that will be used for building the session factory;
- BuildSessionFactory: allows setting parameters on the default session factory or returning an existing one;
- CreateInstance: raised before NHibernate creates a default instance, to allow developers to return one;
- EntityInserting: raised before an entity is inserted, allowing developers to cancel the operations or to set entity parameter;
- EntityUpdating: raised before an entity is updated, allowing developers to cancel the operations or to set entity parameter;
- EntityDeleting: raised before an entity is deleting, allowing its cancellation;
- EntitiesSelecting: raised before a select operation is performed;
- EntityInserted: raised after an entity was inserted;
- EntityUpdated: raised after an entity was updated;
- EntityDeleted: raised after an entity was deleted;
- EntitiesSelected: raised after a select operation was performed;
- OperationCompleted: raised after an operation completes (select, insert, update or delete).
If no handler for CreateInstance is supplied, NHibernateDataSource will try to create an entity using Activator.CreateInstance.
EntitySelecting is raised regardless of the Mode (Hql or Linq), but it will have different values in its argument: a query string plus parameters in the case of Hql and an IQueryable instance for Linq.
EntityInserting, EntityUpdating and EntityDeleting allow the modification of properties of the entity in the parameter, but not the replacing of the entity itself.
OperationCompleted is always called, except in the event of an exception.
It also exposes a couple of properties:
- Mode: one of the two operation modes, Hql or Linq. If Hql is used, then the Hql property must be set; otherwise, it’s EntityName that is required;
- Hql: an NHibernate HQL query string;
- EntityName: the name of an entity that the control will work with; only required for Mode Linq or for inserts, updates or deletes;
- RefreshBeforeUpdate: whether NHibernate should refresh the properties of an entity before updating or deleting it;
- MaximumRecords: the optional maximum number of records to retrieve, if paging is not used (PageSize and PageIndex);
- PageIndex: the page index to retrieve;
- PageSize: the page size to retrieve;
- SessionFactory: a session factory that will be used instead of a default created one;
- SelectParameters: a collection of parameters to be applied to the Hql string;
- InsertParameters: a collection of parameters for the insert operation;
- UpdateParameters: a collection of parameters for the update operation;
- DeleteParameters: a collection of parameters for the delete operation.
And, of course, exposes the basic operations: select is the default, but Insert, Update and Delete methods are available.
NHibernateDataSource will check if the SessionFactory property is set, otherwise, it will build its own Configuration instance and raise the Configure and BuildSessionFactory events. The generated session factory is then stored in the InternalSessionFactory static property for caching.
Then, the NHibernateDataSourceView, which is the responsible for the actual querying, inheriting from QueryableDataSourceView:
And the NHibernateDataSourceMode:
Finally, all of the event arguments:
Now, let’s see concrete examples of its usage. First, using Mode Hql:
You can see that the Hql property has a parameter, price, which is bound to a parameter in SelectParameters with the same name. Each parameter is an instance of the Parameter class, here I am using a parameter with a static value (Parameter) and another that takes a value from the query string (QueryStringParameter), but others exist. To help with NHibernate insert and update operations, I created a new Parameter class, EntityParameter, that knows how to retrieve a en entity or a proxy to an entity:
As for Mode Linq, an example using a QueryExtender is in order:
The LINQ query produced by the NHibernateDataSource is intercepted by the QueryExtender and a where (SearchExpression) and a order by (OrderByExpression) clauses are added to it. Other expressions can be used, inheriting from DataSourceExpression, and some take parameters of type Parameter. Do notice that filtering and sorting is performed server-side, not client-side.
Of course, this can certainly be improved, let me hear your thoughts and questions.
And that’s it. Enjoy!
Wouldn’t it be good if SharePoint would allow the registration of custom functions that could be used in XSLT stylesheets? Well, as it happens, it does!
Some of the classes that allow XSLT processing – DataFormWebPart, ContentByQueryWebPart - have a virtual method called ModifyXsltArgumentList that can be used for registering custom functions. Sadly, XsltListViewWebPart, XlstListFormWebPart, among others, are sealed, and thus do not allow this.
Let’s forget about the MyFunctions class and pretend that it has a few public instance methods that we want to expose to SharePoint. Mind you, because this class will be instantiated in a SharePoint context, it will have access to SPContext.Current, and from here, to the whole of SharePoint!
In a XSLT script, we need something like this in order to access our extension functions:
Did you notice xmlns:my=”urn:MyFunctions”? This should be identical to the namespace that you used inside ModifyXsltArgumentList.
And to call one of the functions:
Again, you need to use the same prefix, my in this case. You can add parameters, as long as they are of base types (strings, number, date/time, booleans, and so on), and the same goes for the result type.
I hear you say: “OK, but now I have to replace all declarations of DataFormWebPart for this new CustomDataFormWebPart!”. Not really, dear reader, ASP.NET offers a great solution for this: tag mapping. In a nutshell, we can ask ASP.NET to replace all instances of a control for another class that inherits from the control’s class.
Now, we could this in several ways, but the best one is to have a feature targeting a WebApplication with a feature receiver that performs a Web.config modification:
When this feature is activated, it adds a line in the Web.config file, tagMapping section, that tells ASP.NET to replace DataFormWebPart for CustomDataFormWebPart in all markup declarations. Of course, it won’t affect code: new DataFormWebPart() will still return a DataFormWebPart!
All is not done, yet. We still need to mark our CustomDataFormWebPart control as safe for declaration in web pages. We do that by adding an entry to the SafeControls section of the Web.config. For a change, I’m going to do this in the SharePoint Solution Manifest, Package.xml:
Notice the $SharePoint.Project.AssemblyFileName$ and $SharePoint.Project.AssemblyFullName$, these are two examples of tokens that will be replaced by Visual Studio when it deploys the solution.
And that’s it! Your custom XSLT extension functions are ready to use!
Besides the classic ASP.NET data source controls, SharePoint brings along its own. These allow us to retrieve data not just from SharePoint, but also from external sources, such as web services or SQL databases. Using SharePoint Designer you end up using these data sources without even knowing, and, specially, ignoring what other options you have. Let’s look at these controls one by one and see how the can be used. I already talked about the SPDataSource and AggregateDataSource, so I won’t cover these here. I also won’t be covering them in depth, but instead will provide an example of how to use them.
A simple example is:
A BdcDataSource let’s you retrieve data from a BCS data source (external content type). This may happen when you don’t have an external list created or you want to call a specific finder method. You need to specify the namespace, LOB instance, entity, and finder method. If the finder needs parameters, you will need to supply them. It can be customized by hosting it in a DataFormWebPart and by applying XSLT.
Here’s an example:
SoapDataSource is the control that retrieves data from a SOAP web service. You specify the URL of the web service, the action to call and the SOAP envelope, together with any required parameters. It should be hosted in a DataFormWebPart and can thus use XSLT for the formatting of its contents.
An example of calling the Lists.asmx web service:
XsltListViewWebPart (External List)
External lists can be displayed using the XsltListViewWebPart. Nothing really new here.
A simple example (of course, do replace the list and view GUIDs):
The XmlUrlDataSource is used for invoking REST web services. Similar to SoapDataSource, you need to pass it the URL, but also the HTTP method and any parameters. I is also usually hosted in a DataFormWebPart.
Here’s an example of calling the weather service I talked about in another post:
The SPSqlDataSource is what SharePoint uses to access a SQL database. If you use SharePoint Designer to add one such data source, you might be surprised to see that it places a SqlDataSource instead. The thing is, SharePoint uses ASP.NET tag mapping to replace any SqlDataSource control for a SPSqlDataSource. Again, we host it inside a DataFormWebPart for easily formatting its contents and you can pass parameters to the SQL.
An example of the markup:
While SPDataSource is generally the most generic and useful control, it cannot do everything, namely, access external sources. For that, we have other options; the AggregateDataSource can be used to bring together data from all of these sources, except SPHierarchyDataSourceControl and SPCalendarDataSource, but you can easily replace these by SPDataSource.
Let me know if you have any questions!
Another post that could be subtitled “How to do Things in SharePoint By Hand”. This time, combining data sources – lists, in this case, but the same can be applied to other source types, such as SOAP (SoapDataSource) or REST (XmlUrlDataSource) web services, hierarchies of sites (SPHierarchyDataSourceControl), calendar (SPCalendarDataSource), XML files (SPXmlDataSource), BCS external lists (BdcDataSource) or even SQL queries (SPSqlDataSource).
Enough talk, here is the code:
If you specify the SeparateRoot parameter as true, in the XSL section, you will get two data sources, one for each data source specified as a concat/datasource entry, you will have to access them separately, using syntax /dsQueryResponse/Tasks/Rows/Row, of course, replacing Tasks for the right name, as specified in the concat/datasource’s name attribute;
If you don’t specify a value for SeparateRoot, the default is false, which means that the values for both data sources will come together in /dsQueryResponse/Rows/Row; you can sort out what records belong to one list or the other using the syntax /dsQueryResponse/Rows[@agg:source='Pages']/Row; this is made possible by the xmlns:agg="http://schemas.microsoft.com/sharepoint/aggregatesource" entry in the xsl:stylesheet declaration, which I’m sure you hadn’t noticed ;
In the XSLT, I am iterating through the first list, and for each item, I get one field value (Author = Creation User) and use it to filter the second list. This is the same that SharePoint Designer does when you insert a linked list data source.
And that’s it. Enjoy!
SharePoint, as usual, offers lots of ways to do things. This time, I’m going to show how one can get a list of the last modified contents, in any SharePoint version and edition.
We’ll use our good friends DataFormWebPart and SPDataSource, together with some XSLT and some nice tricks. We will be able to specify the number of items to return through the query string, otherwise it will default to 5. I’m going to keep it simple, but you can certainly improve it.
We add a DataFormWebPart with an inline SPDataSource that uses DataSourceMode of CrossList. This allows querying multiple lists at once. The actual query is specified in the SelectCommand property. In this case, I am specifying it as:
What it means is:
Search recursively all subsites (Scope=’Recursive’);
Only search lists and document libraries of type Wiki Page Library (ServerTemplate=’119’);
Limit the returned results to the value passed in parameter TopN (RowLimit);
Only return files (FSObjType = 0) containing .aspx in its name;
Return fields List Title (ListProperty Name=’Title’), List ID (ListProperty Name=’ID’), Object Type (FSObjType), ID, Title, File Location (FileRef), File Directory (FileDirRef), File Name (FileLeafRef), Last Modification User (Editor) and Last Modification Timestamp (Modified);
Order by the List Title.
The markup for the DataFormWebPart is as follows:
The ParameterBindings section includes an entry that gets a TopN parameter from the query string, and if one is not there, sets the default to 5. This parameter is passed to the SPDataSource through a DataFormParameter.
While we are iterating through the results, we call the ddwrt:NameChanged extension function upon the value of ListProperty.Title to check if we have changed to a new list, in which case, we add a new row with just its name. Inside each list, items are obtained where they match the list and sorted by the ddwrt:FormatDateTime function according to its last modification timestamp.
I think that’s it. Hope you find it useful.
OpenWeatherMap.org offers a nice service for obtaining current and forecast weather conditions. Go visit it, and search for the “weather in your city”. In the results page, by hovering the link, you will get the id for the city you are interested in; for example, for “Coimbra, Portugal”, it is 2740637 (http://openweathermap.org/city/2740637).
In a SharePoint page, add a XML Viewer Web Part and point it to the address of the OpenWeatherMap.org web service: http://api.openweathermap.org/data/2.5/weather?id=2740637&mode=xml&units=metric. Of course, do replace the id and also the unit, if you like. Documentation for the web services is available at http://openweathermap.org/api. Next, add the following XSLT transformation:
This will add an image for the current status with description and the current temperature. Yes, I could have used a single xsl:template, but I was lazy!
After you save the page, you will get a nice status like this:
I will probably write a post on displaying the forecast. In the meantime, enjoy!
Before you ask, yes, I know about GetDistinctFieldValues, but it is marked as deprecated, which means it may go away in a future version of SharePoint and besides it can’t get distinct values for all fields – Title, for instance.
You declare it as a regular TextBox, plus a ListName and a FieldName properties:
And when it runs, it will present something like this:
In SharePoint, there are several web parts that allow us to have different contents depending on some conditions:
LoginView (ASP.NET): allows the definition of templates per authenticated or anonymous user;
SPSecurityTrimmedControl: displays contents based on the security permissions of the current user;
EditModePanel: for displaying contents in a web part page depending on its edit mode;
- AuthoringContainer: displays content depending on whether the current user has write or read rights on the current page or if it has an associated list item;
DataViewWebPart: allows the passing of parameters and the usage of XSL for rendering logic.
I imagine you are now rolling your eyes: DataViewWebPart? how come? Well, because it doesn’t need to point to a specific list or view (unlike XsltListViewWebPart), it is very useful for markup-based customizations that will only depend on parameters.
Let’s see an example:
You can use this technique for:
Including scripts and stylesheets;
Including server-side controls.
It’s just a matter of rolling out some XSL to the rescue!
You may be already familiar with the available parameters, but you can find the full list here: http://msdn.microsoft.com/en-us/library/office/ff630170(v=office.15).aspx.
Another SharePoint Designer-only solution that may come in handy! ;-)
ASP.NET includes a valuable yet not well known extension point called the page parser filter. I once briefly talked about it in the context of SharePoint, but I feel a more detailed explanation is in order.
A page parser filter is a class with a public parameterless constructor that inherits from PageParserFilter and is registered on the Web.config file, in the pages section, pageParserFilterType attribute. It is called when ASP.NET is compiling a page, the first time it is called, for every page. There can be only one page parser filter per web application.
Why is it a parser? Well, it parses – or, better, receives a notification for - every control declared on the markup of a page (those with runat=”server” or contained inside of), as well as all of the page’s directives (<%@ … %>). The control declarations include all of its attributes and properties, the recognized control type and any complex properties that the markup contains. This allows us to do all kinds of crazy stuff:
Inspect, add and remove page directives;
Setting the page’s compilation mode;
Insert or remove controls or text literals dynamically at specific places;
Add/change/remove a control’s properties or attributes;
Even (with some reflection magic) change a control’s type or tag.
So, how do we all this? First, the parser part. We can inspect all page directives by overriding the PreprocessDirective method. This is called for all page directives:
The page’s compilation mode is controlled by GetCompilationMode:
As for adding controls dynamically, we make use of the ParseComplete method:
Same for changing a control’s properties:
And even changing the control’s output tag or instance type:
Why would we want to change a control’s type? Well, thing about generics, for once.
And now the filtering part: why is it a filter? Because it allows us to filter and control a number of things:
The allowed master page, base page class and source file;
The allowed controls;
The total number of controls allowed on a page;
The total number of direct and otherwise references on a page;
Allow or disallow code and event handler declarations;
Allow or disallow code blocks (<%= … %>, <%: … %>, <% … %>);
Allow or disallow server-side script tags (<script runat=”server”>…</script>);
Allow, disallow and change data binding expressions (<%# … %>);
Add, change or remove event handler declarations.
All of the filtering methods and properties described below return a Boolean flag and its base implementation may or may not be called, depending on the logic that we want to impose.
Allowing or disallowing a base page class is controlled by the AllowBaseType method (the default is to accept):
For master pages, user controls or source files we have the AllowVirtualReference virtual method (again, the default is true):
Controls are controlled (pun intended) by AllowControl, which also defaults to accept:
This may come in handy to disallow the usage of controls in ASP.NET MVC ASPX views!
The number of controls and dependencies on a page is defined by NumberOfControlsAllowed, NumberOfDirectDependenciesAllowed and TotalNumberOfDependenciesAllowed. Interesting, the default for all these properties is 0, so we have to return –1:
Direct dependencies are user controls directly declared in the page and indirect ones are those declared inside other user controls.
Code itself, including event handler declarations, are controlled by AllowCode (default is true):
If we want to change a data binding expression, we resort to ProcessDataBindingAttribute, which also returns true by default:
For intercepting event handlers, there’s the ProcessEventHook, which likewise returns true by default:
And finally, for code blocks, server-side scripts and data binding expressions, there’s the ProcessCodeConstruct method, which likewise also allows everything by default:
This was in no means an in-depth description of page parser filters, I just meant to give you an idea of its (high) potential. It is very useful to restrict what end users can place on their pages (SharePoint style) as well as for adding dynamic control programmatically in specific locations of the page, before it is actually built.
As usual, let me hear your thoughts!