Dailycode.info

Short solution for short problems

Free movie, books and CD database part 1

Recently I started a new project, for personal use. I have a large collection of CD's and DVD's, this taking up more and more place. So now I was looking for software to keep an inventory of all these multimedia. I could find some, but the most interesting where not free. So I decided to make my own. This is a really nice porject in which I try some new stuff. When it is ready I will make it as a free download including the source code. For now you it will cover 3 types of multimedia: Audio CD's, Movies and books. There is a build in lend out system and some other cool stuff. I choose not to overload the objects with to much properties.

Here's a first look at the program:

I store all data in XML files. When data is first called I cache it, so the program runs smoothly. Since it is only text, it will not take to much memory.  

The caching is something I'm looking into with much interest. Before you start caching, you'll have to look into what to cache and when. For example, you could load all data at program startup, but then the startup takes long. The program I'm making consists of 3 big parts, Audio, Video and Books. I will create the system so that you can disable and enable these functionalities, so this makes caching more complicated. It's really fun to think of the best and most performant ways to cache.

What I also will implement in the system is an online update. I got some ideas in my head, just trying them out as soon as the first version of the program is almost ready. It's offcourse important to have the update procedure ready before I will release the first version.

I can assure you that you will find updates on this program on regular basis. It's a hobby!

So the first version is ready for publication. You will find it soon as a download on this site. The last step is testing and user manual generation. My wife will do the end user testing and I will generete a short manual.

Read more about this in the second part 2. 

Greetings and God bless this world!

 


The data source control failed to execute the insert command

In my test evironment, just like that, the workflows on a document library sotp working. Normally it starts on creation of a new document and the other can only be started manually. None of them worked anymore.

So what I did to resolve the problem was to remove the workflow from the library together with the complete history of the workflow. Then I opened the SharePoint designer and associated the workflows again with the list. Problem solved. I don't know why it happened, but for all I can google its a bug in SharePoint.


How to hide WSS list item properties

I was working on a SharePoint project, where I need to test and set an item field, but this field should not be visible to users.

After looking in SharePoint configuration, I realized it could not be done this way. So the solution I found was to edit the tp_fields in the 'alllist' table of the content database. First you have to look for the tp_id of the list where you want to hide the property. Then you copy the contents of the tp_fields field and paste it in a sql command like this:

update alllists 
set tp_fields = '12.0.0.4518.0.0

<Field Name="_Status" Hidden="TRUE" FromBaseType="FALSE" Type="MultiChoice" 
DisplayName="Status" Required="FALSE" FillInChoice="FALSE" ID="{1dab9b48-2d1a-47b3-878c-8e84f0d211ba}" 
Version="7" StaticName="_Status" SourceID=http://schemas.microsoft.com/sharepoint/v3/fields 
ColName="ntext2" RowOrdinal="0">
  <Default>Draft</Default>
  <CHOICES>
    <CHOICE>Draft</CHOICE>
    <CHOICE>Reviewed by Author</CHOICE>
    <CHOICE>Reviewed by Reviewer</CHOICE>
    <CHOICE>Reviewed by Safety</CHOICE>
    <CHOICE>Reviewed by QS</CHOICE>
    <CHOICE>Released by Reviewer</CHOICE>
    <CHOICE>Released by Sefaty</CHOICE>
    <CHOICE>Approved by Management</CHOICE>
  </CHOICES>
</Field>

</Field><Field Name="Author"/>'
where tp_id = '8257d5d1-789d-37cd-b4sc-bf61f4761451'

The ... replace the other fields in the list. So when you set hidden="true" the field is still accesible trough code, but not in SharePoint gui, or even SPD. If you have made a view that consited this field, it will keep showing the field. But in a new view, the field will not be available anymore. So if you still want it to appear in a view, then create the view before you hide the field or just unhide it for a moment to create a view and hide it again afterwards.


Get email from SPUser field in SharePoint

Whe you are working with WSS workflows or webparts, you will come to the point you have to send emails to users.

If you are using a single user field (not allowed to enter multiple users) the value is returned as a string. So if you choose to show the users name and you want to email this users, you cannot get his email out of this field. So how can we get the users email? Here's some functions that might help:

First I get the authors name out of a field in a list:

searchPerson = _doc["Author"].ToString().Substring(_doc["Author"].ToString().IndexOf("#") + 1);
to =  GetEmail(searchPerson);

Sometimes Sharepoint stores #? characters after the names, so multiple values are allowed. The substring will get them out and return the users name correct. E.g. The value could be Mark, Deraeve#2 and after the substring it will be: Mark, Deraeve 

The GetEmail fuction will look for the user in the rootweb, if a user is present in the current web, he will be on the rootweb. Here the code that returns the users email:

        private string GetEmail(string username)
        {
            foreach (SPUser user in SPContext.Current.Site.RootWeb.AllUsers)
            {
                if (user.Name == username)
                {
                    return user.Email;
                }
            }
            return String.Empty;
        } 

So now you get the users email. You could prevent from looping through all users if you have the users login name, but in my case it the users full name, so I cannot use ...AllUsers[loginname] and I have to loop through the entire users collection.

If the user field allows multiple values, you can retrieve the email with the SPFieldUserValueCollection. Because it allows multiple users, it will not return a string, but a SPFieldUserValueCollection. We can use this to build up a list of email addresses:

SPFieldUserValueCollection col = (SPFieldUserValueCollection)_doc["Users"];
StringBuilder sb = new StringBuilder();
foreach (SPFieldUserValue user in col)
{
if (!IsGroup(user,ref sb))
      {
            sb.Append(user.User.Email + ";");
}
}

I will add some extra code that gets the emails of the users who are in a group:

private string GetEmails(string groupName)
        {
            foreach (SPGroup group in SPContext.Current.Site.RootWeb.Groups)
            {
                if (group.Name == groupName)
                {
                    StringBuilder ret = new StringBuilder();
                    foreach (SPUser user in SPContext.Current.Site.RootWeb.Groups[groupName].Users)
                    {
                        ret.Append(user.Email + ";");
                    }
                    return ret.ToString();
                }
            }
            return String.Empty;
        }

I used a function IsGroup, this function simply checks if it is a user or a group and adds all the users in the group to the email addresses (ref sb):

private bool IsGroup(SPFieldUserValue userOrGroup, ref StringBuilder sb)
        {
            SPGroup qsgroup = null;
            try
            {
                qsgroup = SPContext.Current.Site.AllWebs[_sopSiteName].Groups[userOrGroup.ToString()
	.Substring(userOrGroup.ToString().IndexOf("#") + 1)];
                //Page.Response.Write("group");
                foreach (SPUser user in qsgroup.Users)
                {
                    sb.Append(user.Email + ";");
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

Just for fun another function I used to check if a user is a member of a particular group:

        private bool UserInGroup(string group)
        {
            SPGroupCollection grps = CurrentUser().Groups;
            foreach (SPGroup grp in grps)
            {
                if (grp.Name.ToLower().TrimEnd() == group.ToLower().TrimEnd())
                { return true; }
            }
            return false;
        }

 


Checkin all items in a document library

When I had a deadlock on a document in a document library, I went looking for a solution. Some suggested that you write a webpart that checks all document in a document library, which are checked in shortterm. 

SPListItemCollection docLibItems = getDocLib().Items;
Page.Response.Write("No of items: " + docLibItems.Count.ToString() +"<br>");
foreach (SPListItem docLibItem in docLibItems)
{
Page.Response.Write("Item: " + docLibItem.Name + " status: " +
docLibItem.File.CheckOutStatus.ToString() + "<br>");
if (docLibItem.File.CheckOutStatus == SPFile.SPCheckOutStatus.LongTerm)
      {
            Page.Response.Write(docLibItem.File.Name.ToString());
            try
            {
                  docLibItem.File.CheckIn("");
            }
            catch (Exception error)
            {
                  Page.Response.Write(error.Message.ToString());
}
}
if (docLibItem.File.CheckOutStatus == SPFile.SPCheckOutStatus.ShortTerm)
      {
            Page.Response.Write("Checking in short term lock out!");
            try
            {
                  docLibItem.File.CheckIn("");
}
            catch (Exception error)
            {
                  Page.Response.Write(error.Message.ToString());
}
}


So I tried it, but it didn't helped me. So at the end I had to delete it and put it back again. Just download the document and "save as" a document on your local machine. That delete the original and upload the document again. The only disadvantage you have is that the creation date and the created by are changed. I had to remove this deadlock fast, but next time this occurs I will try to find a better solution to this problem. You can first try the code above, because in some cases it will work. I found people with the same problem and for them this code worked.


BlogEngine.NET 1.5.0.7

I am working on the update of this blog. There's no possibility to update directly from 1.1.0.2 to 1.5.0. So I will have to import all my posts, categories etc...

Then I'll have to look for a nicer theme and adapt the layout to my needs. Put in the Google adds and stuff...

I hope you like the update, it will be visible in e few days...

You can check the progress here. All comments on the demo will be deleted when I migrate the site. Please feel free to comment here on the looks. I choose the default scheme with some minor adjustments.