Contents tagged with ASP.NET
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;
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! ;-)
Sometimes, when you are using a SPDataSource control to bind to some list control, you might need, inside of it, to fetch information from the item you are iterating over.
Imagine, for example, that you are displaying a list of sites. As usual with SharePoint, there are lots of options for doing this, but consider the SPDataSource approach, which doesn’t require any coding:
But now you want to display all lists of each subsite… What would you do then?
OK, we need to get, for each site listed, its id, and store it in some server-side control, such as HiddenField. Next, we add a nested SPDataSource, this time with DataSourceMode=ListOfLists, and add a WebID parameter:
If you are curious, the MSDN page SPDataSource.SelectParameters lists all predefined parameters that the SPDataSource will recognize automatically, and this page in Solutionizing .NET lists all fields returned by SPDataSource, in all of its modes. BTW, a great resource!
A common request is the ability to have one drop down list (the child) being filled after another one (the parent) has; this is usually called cascading drop down lists.
First, let’s create two lists: Parent and Child. Connect the Child to the Parent through a lookup field that points to the Parent’s ID field and call this lookup Parent. Add some records to it.
On SharePoint Designer create a new web part page. Find some space and add two DropDownList controls:
Next, add two SPDataSource controls:
Pay attention to a couple of things:
- I am using the standard ID and Title columns, but you can use whatever you want;
If you prefer to have the parent DropDownList initially unselected, use the following markup instead:
AppendDataBoundItems makes sure that any items added from a data source control are appended to any existing ones.
Of course, you can have any number of nested DropDownList controls, just follow the same logic.
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!
SharePoint Designer 2013 workflows brought along new and quite welcome features. I will list my favorite ones.
First, the ability to define stages (blocks of instructions) and to jump (yes, goto-style!) between them. This permits a better organization of our code and because of conditional jumps, even includes the ability to reuse code and to loop between stages.
Next one is stage-level loops. We have two flavors: one where the loop count is predefined from an Integer variable and the other where a condition is used to determine its end.
Then we have a new type of variables, Dictionary, and three associated actions: build a dictionary with values, get an item from a dictionary and count the number of items in it. Each Dictionary item can be of a different type, and it is even possible to have items of type Dictionary. A Dictionary can be indexed by its key or by position, which is very useful to use inside loops.
It is now possible to start list and site workflows, but only SharePoint 2010 are supported. Workflows can be started synchronously, in which case, the originating workflow will wait for the result, or asynchronously, aka, fire and forget. Depending on the workflow selected, it may be necessary to specify values for its parameters.
Also new is the ability to assign tasks and start approval processes.
A perhaps not so used one is the capability to start a document translation process. The name is misleading, since it can also be used to translate list fields. The result translation is stored in another list.
Finally, we have the ability to call an HTTP web service. This will mostly used to call REST-style web services, but nothing prevents us from calling SOAP, since we can build a SOAP request using the string utility actions that the Designer offers. We can specify both request contents and headers, and retrieve the result, headers and HTTP status code. The problem is, SharePoint Designer workflows can only process results coming as JSON, not XML, but there are a number of translation web services that can be used to turn XML into JSON.
All in all, very useful additions!
SharePoint 2013 Designer workflows now has two new interesting options: the ability to call HTTP web services and the option to loop over some code a number of times. This, together with the new REST API, which supports querying lists and returning data in JSON, allows iterating through list items in a workflow, something that was not possible before.
In order to demonstrate this, let’s create a new Site Workflow in SharePoint Designer, that will iterate through the Tasks list:
Call it Process Tasks, for example, and make sure you select SharePoint 2013 as the platform type.
In the workflow designer, let’s start by creating a new stage, call it Retrieve Tasks:
In it, we add a new Set Workflow Variable action which creates a new String variable called url with the value “http://sp2013/_api/web/lists/getbytitle('Tasks')/items”. This uses the new REST API, and you can pass in additional options, such as for ordering by the DueDate field in descending order:
http://sp2013/_api/web/lists/getbytitle('Tasks')/items?$filter=DueDate gt DateTime’2014-07-31T00:00:00’
Next, we add a Dictionary variable (Build a Dictionary action), call it requestHeaders, and initialize it as this:
Both “Accept” and “Content-Type” entries are of the String type and they both contain the value “application/json;odata=verbose”, SharePoint REST API understands this and sets the response content type appropriately as JSON. If we don’t pass these values, the output would come as XML.
Following, add an Call an HTTP Web Service action and set its properties. The request will be the url variable:
Response content will go to a new variable called responseContent:
Response headers will go to a new variable called responseHeaders:
And the same goes for the response code (variable responseCode):
Then we set the request headers to be the requestHeaders variable we created just now, by clicking on the properties for the Call an HTTP Web Service action:
Now, create a new stage, call it Process Tasks, and, at the end of the initial stage, add a Go to Process Tasks action.
On the Process Tasks stage, add a Get an Item from a Dictionary action, set the item as d/results, the source variable reponseContent and the output to a new variable of type Dictionary called list. Then count items from this list variable using a Count Items in Dictionary action and store the result in a new Integer variable called count. This variable will tell us how many times we have to loop. Finally, create a new Integer variable called index and set it to 0 (Set Workflow Variable), this will be the loop index.
Next, add a loop (Loop n Times), call it Loop Task Items, and set the loop variable to count. Inside the loop, get value d/results([%Variable: index%]) using a Get an Item from a Dictionary action from responseContent and store it in a new Dictionary variable called item. Get some fields (Get an Item from a Dictionary) from the item variable, such as Title and DueDate (mind you, these will be task item fields) and store them in appropriate variables and do whatever you want with them, like logging its contents (Log). Time to increment the loop counter: add a Do Calculation action and in it increment the index variable into a new Integer variable called indexPlusOne. Then set the index variable to be the indexPlusOne (Set Workflow Variable). Finally, exit the loop and set the workflow status (Set Workflow Status action) to Finished. At the end of the stage, select Go to End of Workflow.
That’s it. Your workflow should look like this:
The new functionality makes SharePoint Designer workflows much more powerful than before. I will continue to talk about it in the following posts.
I have already talked about SignalR in this blog. I think it is one of the most interesting technologies that Microsoft put out recently, not because it is something substantially new – AJAX, long polling and server-sent events have been around for quite some time -, but because of how easy and extensive they made it.
Most of the examples of SignalR usually are about chat. You know that I have been digging into HTML5 lately, and I already posted on media acquisition using HTML5’s getUserMedia API. This time, however, I’m going to talk about video streaming!
I wrote a simple ASP.NET Web Forms control that leverages SignalR to build a real-time communication channel, and this channel transmits images as Data URIs. The source of the feed comes from getUserMedia and is therefore available in all modern browsers, except, alas, one that shall remain unnamed. Any browser, however, can be used to display the streaming feed.
So, the architecture is quite simple:
- One SignalR Hub for the communication channel;
- One ASP.NET Web Forms control, that renders an HTML5 VIDEO tag that is used to display the video being acquired, on any compatible browser.
Here are some nice screenshots of my now famous home wall, where one of the browser instances, Chrome, is broadcasting to Firefox, Opera and Safari.
So, all we need is a control declaration on an ASP.NET Web Forms page, which could look like this:
The non-ordinary properties that the VideoStreaming control supports are:
Interval: the rate in milliseconds that the control broadcasts that the video is being broadcast;
Source: if the control is set as a streaming source, or just as a receiver (default);
And a simple CANVAS element for Target:
The reason for the two main streaming modes, Target and Event are flexibility: with Target, you directly draw the streamed picture on a CANVAS or IMG (it will detect automatically what to use), which needs to be already present, and with Event, you can do your own custom processing.
The source for the VideoStreaming control is this:
Renders a VIDEO tag element with the specified Width and Height;
Register a SignalR hub;
Removes any eventual VIDEO-related attribute that may be present on the control declaration;
Of course, we now need the hub code, which is as simple as it could be, just a method that takes the image as a Data URI and its original dimensions and broadcasts it to the world:
And finally the simple enumerations used by the VideoStreaming control:
And there you have it! Just drop the VideoStreaming control on an ASPX page and you’re done! If you want to have it broadcast, you need to set its Source property to true, for example, on the containing page:
That’s it. Very simple video streaming without the need for any plugin or server. Hope you enjoy it!
I wanted to be able to capture a snapshot and to upload it in AJAX style. Of course, if you know me you can guess I wanted this with ASP.NET Web Forms and client callbacks!
OK, so I came up with this markup:
The properties and events worth notice are:
Width & Height: should be self explanatory;
PictureTaken: a handler for a server-side .NET event that is raised when the picture is sent to the server asynchronously.
startCapture: when called, starts displaying the output of the camera in real time;
stopCapture: pauses the update of the camera;
takeSnapshot: takes a snapshot of the current camera output (as visible on screen) and sends it asynchronously to the server, raising the PictureTaken event.
When the startCapture method is called, the PictureSnapshot control (or, better, its underlying VIDEO tag) starts displaying whatever the camera is pointing to (if we so authorize it).
Here is an example of one of my home walls… yes, I deliberately got out of the way!
OK, enough talk, the code for PictureSnapshot looks like this:
As you can see, it inherits from WebControl. This is the simplest class in ASP.NET that allows me to output the tag I want, and also includes some nice stuff (width, height, style, class, etc). Also, it implements ICallbackEventHandler for the client callback stuff.
You may find it strange that I am setting explicitly the WIDTH and HEIGHT attributes, that is because VIDEO requires it in the tag, not just on the STYLE. In the way, I am removing any CROSSORIGIN, SRC, MUTED, PRELOAD, LOOP, AUTOPLAY, MEDIAGROUP, POSTER and CONTROLS attributes that may be present in the markup, because we don’t really want them.
The PictureTakenEventArgs class:
Finally, a simple event handler for PictureTaken:
Pictures arrive as instances of the Image class, and you can do whatever you want with it.
As always, feedback is greatly appreciated!
Continuing with my quest for reusable, no dependencies, Web Forms AJAX controls, this time I wanted a replacement for the venerable UpdatePanel control. Specifically, I wanted to address the following issues:
- Allow the partial update of a region on my page, including all of its controls;
- Have the ability to only send data for controls living inside my control, not everything else on the page (read, __VIEWSTATE);
I ended up with a CallbackPanel control, which is what I am going to talk about. Here is its declaration:
The CallbackPanel control supports some properties:
SendAllData: if all the data in the form should be sent, including viewstate, or just the data for the controls inside the CallbackPanel (default is false);
For causing an update, we call its callback function, passing it a parameter and an optional context:
The most important property in CallbackPanel is the server-side event, OnCallback: this is raised whenever the callback function is called:
This event receives a CallbackEventArgs argument, which is nothing more than:
And finally, the code for the CallbackPanel itself:
Again, it is implementing ICallbackEventHandler, for client callbacks, but this time it is inheriting from Panel, which is a nice container for other controls. The rest should be self-explanatory, I guess. If you have questions, do send them to me!
As always, hope you like it!
- Set up a control that renders an AUDIO tag;
- Generate a voice sound from the passed text parameter on the server and save it into an in-memory stream;
- Convert the stream’s contents to a Data URI;
- Return the generated Data URI to the client as the response to the client callback.
So, first of all, my markup looks like this:
As you can see, the SpeechSynthesizer control features a few optional properties:
- Age: the age for the generated voice (default is the one of the system’s default language);
- Gender: gender of the generated voice (same default as per Age);
- Culture: the culture of the generated voice (system default);
- Rate: the speaking rate, from –10 (fastest) to 10 (slowest), where the default is 0 (normal rate);
- Ssml: if the text is to be considered SSML or not (default is false);
- Volume: the volume %, between 0 and 100 (default);
- VoiceName: the name of a voice that is installed on the server machine.
The Age, Gender and Culture properties and the VoiceName are exclusive, you either specify one or the other. If you want to know the voices installed on your machine, have a look at the GetInstalledVoices method. If no property is specified, the speech will be synthesized with the operating system’s default (Microsoft Anna on Windows 7, Microsoft Dave, Hazel and Zira on Windows 8, etc). By the way, you can get additional voices, either commercially or for free, just look them up in Google.
Without further delay, here is the code:
As you can see, the SpeechSynthesizer control inherits from HtmlGenericControl, this is the simplest out-of-the-box class that will allow me to render my tag of choice (in this case, AUDIO); by the way, this class requires that I decorate it with a ConstructorNeedsTagAttribute, but you don’t have to worry about it. It implements ICallbackEventHandler for the client callback mechanism. I make sure that all of AUDIO’s attributes are removed from the output, because I don’t want them around.
Inside of it, I have an instance of the SpeechSynthesizer class, the one that will be used to do the actual work. Because this class is disposable, I make sure it is disposed at the end of the control’s life cycle. Based on the parameters being supplied, I either call the SelectVoiceByHints or the SelectVoice methods. One thing to note is, we need to set up a synchronization context, because the SpeechSynthesizer works asynchronously, so that we can wait for its result.
A full markup example would be:
And that’s it! Have fun with speech on your web apps!