May 2006 - Posts
So you want to send all your users of your Community Server community i.e. a newsletter? But some users may contact you and say they don't want the newsletters anymore.
In Community Server you can send mass mail to all users of a certain role. By default all registered users is added to the role - you've guessed it - "Registered Users". But if you use that role for your mass mailings you won't be able to exclude users on demand. Taking them out of the role "Registered Users" would not be a good idea. So you would need another role to use for your mass mailings. Let's say we want to use a role called "Newsletter" for the mass mailings. We would then need a way to put all newly registered users into that role as well. Don't worry, you don't need to open the source code of CS and modify it. Just open communityserver.config in your favourite editor. In the Core section you can se a row with the following:
defaultRoles = "Everyone;Registered Users"
This row determines which role a user is added to at registration. So we add our "Newsletter" role to it, like:
defaultRoles = "Everyone;Registered Users;Newsletter"
That's it! Now all of your users is added to the "Newsletter" role at registration, and you can send mass mail to it. If someone wants to opt-out, just remove them from the "Newsletter" role.
Yeah, I know, I forgot one thing. You might of course have a whole lot of existing users already, how do you add those? One way to do that is with a T-SQL script.
CREATE TABLE #NewRole (
[UserId] [uniqueidentifier] NOT NULL ,
[RoleId] [uniqueidentifier]
)
INSERT INTO #NewRole (UserID)
SELECT UserID FROM aspnet_Users WHERE ApplicationID = 'your applicationID here'
AND UserID <> 'your anonymous UserID here'
AND RoleID <> 'your Newsletter roleID herer'
UPDATE #NewRole
SET RoleID = 'your Newsletter roleID here'
DROP TABLE #NewRole
INSERT INTO aspnet_UsersInRoles (UserID, RoleID)
SELECT UserID, RoleID FROM #NewRole
The red text should be replaced with:
AplicationID - ApplicationID from your aspnet_Applications table (if you have more than one be sure to choose the right one)
Anonymous UserID - UserID from your aspnet_Users table. There would be one anonymous user per application. So the same here if you have multiple applications, be sure to get the correct one.
Newsletter RoleID - RoleID from your aspnet_Roles table (The new role you created for massmailing). Again there's one set of roles collection for each application.
Note: Before you go ahead and run the T-SQL on your live DB, you might want to try it in a test environment first, to see that it works as expected. And of course make sure you do a DB Backup before you run it live. You could also test it on the live DB by first omitting the last INSERT statement, and adding a SELECT * FROM #NewRole before the DROP TABLE statement. That would list all the additions that will be made to the aspnet_UserInRoles table. Such a test script would look like:
CREATE TABLE #NewRole (
[UserId] [uniqueidentifier] NOT NULL ,
[RoleId] [uniqueidentifier]
)
INSERT INTO #NewRole (UserID)
SELECT UserID FROM aspnet_Users WHERE ApplicationID = 'your applicationID here'
AND UserID <> 'your anonymous UserID here'
AND RoleID <> 'your Newsletter roleID herer'
UPDATE #NewRole
SET RoleID = 'your Newsletter roleID here'
SELECT * FROM #NewRole
DROP TABLE #NewRole
If any of you readers are more skilled in T-SQL then me, you might have better suggestions for this? Write a comment to this post and let me know.
Since I run a couple of Community Server sites myself, and also have followed the progress of this application since the end of 2003 (for example I coordinated the translation work for the first versions, and I was honored with a CS MVP title a while ago), I am going to also write some posts about CS in this blog.
I also write about CS in my blog at http://communityserver.se but it’s all in Swedish there, so you might not understand much.
So in this first post, I’d like to show you a little trick I contributed to the CS Forums a while back.
If you are familiar with CS you know that it has a list on the home page, which shows the latest posts from the blogs. But there might be situations when you don’t want everyone’s blog posts to show up there. Instead you might want to use that list for announcements and similar, which you have control over yourself. CS is built on a lot of ASP .NET server controls, and fortunately the list I am talking about is also a server control. Open the default.aspx from the root directory of your CS web in i.e. notepad and have a look. You should be able to find a tag like this:
<Blog:AggregatePostList runat="Server" PageSize=5 id="AggregateBlogPosts" EnablePaging="false" EnableTitle="false">
What you don’t see there is that there are more parameters available to this control. One of them, which we are going to use here is the “ApplicationKey” parameter. With it you can determine which blogs latest posts that should be shown. So If the blog I want to show has the ApplicationKey MyBlog, I should edit the tag to look like this:
<Blog:AggregatePostList runat="Server" PageSize=5 id="AggregateBlogPosts" EnablePaging="false" EnableTitle="false" ApplicationKey=”MyBlog”>
But how do I know the ApplicationKey you might wonder? One way to find out is to go to your blog in a browser. If the link is for example: http://mydomainname.com/blogs/MyBlog. The ApplicationKey is the word after blogs in the path. You can also find the ApplicationKey for a blog in CS’s ControlPanel, although it might be hard to find.
In an earlier post I talked a little about recieving the XML result from a request to a WSS Web Service. In this post I thought I talk a bit more on this topic. I said in the previous post that I built a couple of classes to recieve the XML results.
To create these classes I also use XML attributes defined in the namespace System.Xml.Serialization. So the classes to hold i.e. LastName and FirstName from a contact list could look like this;
Imports System.Xml.Serialization
<XmlRoot(ElementName:="listitems", Namespace:="http://schemas.microsoft.com/sharepoint/soap/")> _
Public Class ListResults
<XmlElement(ElementName:="data", Namespace:="urn:schemas-microsoft-com:rowset")> _
Public Data As ListData
End Class
Public Class ListData
Public Sub New()
End Sub
<XmlAttributeAttribute("ItemCount")> _
Public ItemCount As Int32
<XmlElement(ElementName:="row", Namespace:="#RowsetSchema")> _
Public Items As ListItem()
End Class
Public Class ListItem
Private m_LastName As String
Private m_FirstName As String
Public Sub New()
End Sub
<XmlAttributeAttribute("ows_Title")> _
Public Property LastName() As String
Get
Return m_LastName
End Get
Set(ByVal Value As String)
m_LastName = Value
End Set
End Property
<XmlAttributeAttribute("ows_FirstName")> _
Public Property FirstName() As String
Get
Return m_FirstName
End Get
Set(ByVal Value As String)
m_FirstName = Value
End Set
End Property
End Class
The ListItem class can easily be extended to hold more fields from the contact list, or customized to hold data from an entirely different WSS list.
Maybe you wonder why the field for LastName has the attribute ows_Title? Well, that's WSS's behaviour that it in a newly created list always create a field called Title. You cannot delete that field, but you can change it's DisplayName. But the underlying field name remains.
You just got to have your RSS subscriptions with you all the time, don't you? Well, I do, at least I like have them with me. That's why I started to look for a mobile RSS reader sometime last year. At the time I didn't find that many of them out there, but the one that I liked the most was NewsBreak from Iliumsoft.
The first view you get is the list of channels.

You can see how many unread/total posts there are for each channel. Also if you notice some of the icons have the letter i on them. That is channels with unread posts that matches keywords I have defined in the application. When I click a channel I get the post list for that channel.

As you can see there are different icons here to. The blur stars means that the post contains one or more of my defined keywords. Clicking a post title here takes me to, you've guessed it, the post itself.

IMO a very easy to read format. When I am done with the post, I click OK and I am back to the post list for the channel.
The application can import and export OPML, you can categorize the channels, filter out read channels. It has Auto Update, notifications of new items, you can choose to place the data files on your external storage card and more.
Works great for me. Give it a try. There's a 30-day evaluation copy for both Pocket PC and Smartphone.
Now you can get your copy of beta 2 of Sharepoint Server (and other Office 2007 products at:
http://www.microsoft.com/office/preview/beta/getthebeta.mspx
A couple of months ago, I needed to create an application which requested a collection of ListItems from a SharePoint list. SharePoint has a couple of built-in web services OOB, and the one I was interested in was 'Lists' (http://Server_Name/[sites/][Site_Name/]_vti_bin/Lists.asmx), and more precisely the GetListItems method. When I got the request to the webservice to work the returned result was of course in XML :-(. A sample of such a return result could be like:
<listitems xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882"
xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"
xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema"
xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<rs:data ItemCount="4">
<z:row ows_<I>Number_Field</I>="6555.00000000000" ows_Created="2003-06-18T03:41:09Z"
ows_ID="3" ows_owshiddenversion="3" />
<z:row ows_<I>Number_Field</I>="78905456.0000000" ows_Created="2003-06-18T17:15:58Z"
ows_ID="4" ows_owshiddenversion="2" />
.
.
.
</rs:data>
</listitems>
I played around a bit for a while and tried different ways to parse the XML results that I had, but couldn't find anything really good, until I found the following excellent article (by Paul Ballard) which described exactly what I was looking for:
http://weblogs.asp.net/paulballard/archive/2005/05/08/406197.aspx
In my case I used the last method described there, and created a couple of classes to put the results in. After that it was a piece of cake to handle the XML results.
I have just managed to logon after the migration of weblogs.asp.net to Community Server 2.1
More Posts