Detect whether web http request is from a valid browser agent

Browser User AgentToday while writing up a small blog module for one of my project, we were to implement a blog post view count feature where in on every blog post view we were to increment its view count field value by one.

Now one check we needed to place before registering a blog post’s view count was that the request that we had received was from a valid browser agent and not from any crawler, spider etc. This would help us get a better and legitimate view count for any blog post.

For accomplishing this task of identifying and validating a http request to be coming from a valid browser agent, not much direct help is available on google.

For the people who are in search of only the SOLUTION, here it goes:

Note: Below solution is in the form of an extension method that can be directly used with your Request object [e.g. Request.IsFromBrowser()]. But if you are using .Net framework version older then 3.0, which does not support extension methods, then remove the “this” keyword at the starting of argument, and call the function by passing your Request object.

 /// <summary>
 /// Specifies whether a request has been made from a valid browser, 
 /// and not from other sources like crawlers, spiders etc.
 /// </summary>
 /// <param name="objRequest">Current Request object</param>
 /// <returns>true is request is from a browser, else false</returns>
 public static bool IsFromBrowser(this HttpRequestBase objRequest)
 {
   return !objRequest.Browser.Crawler
       && objRequest.Browser.IsBrowser(objRequest.Browser.Browser);
 }

Now if you are interested in UNDERSTANDING the solution, please continue reading further:

All information related to our task is available in the user-agent string that we receive in the http request. But dont worry about parsing it out and matching up values with valid browser value sets. In DotNet framework, Microsoft has done the hard work of parsing these user agent strings in its HttpRequestBase class. It has also implemented a very efficient and extendable browser detection method where in it has stored browser agent information for various available browsers currently out there in market under {Windows}\Microsoft.NET\Framework\{Framework version}\Config\Browsers folder. Here in you would find various files with “.browser” extension. These are xml files with that browser’s user agent string’s parsing information. DotNet framework uses these as base information to parse current HttpRequest’s user agent string.

If you know of any browser agent that is not covered under these folder, you can create a “.browser” file for this new browser agent and add it under the above specified “browser” folder. Once this is done the dotNet framework’s IsBrowser function would detect this new user agent string file as a valid browser.

Note: If you want to get more information about the browser that has sent the http request (e.g. major/minor version; capabilities like css, javascript support, is touch enabled, can send emails, have cookies enabled; etc.), you would find it under various properties of Request.Browser object.

Happy Browser Detection !!!

A Very Inspiring Story of Mr.Narayan and Ms.Sudha Murty

InspirationThere’s no introduction needed for Mr. Narayan Murty, the founder of India’s most reputed software company “Infosys”, and his wife Ms. Sudha Murty.

Today I came across a very inspiring story about this great couple POWER OF LOVE – A Letter by Ms. Sudha Murthy.

Heads off to this wonderful couple and to their success in life !!!

Wrap a continuous text using CSS

CSS 3In a project, we had to show some text entered by user in a label (i.e. span tag of html) back on the view page. We had provided width of 100px to this label so that it fits well with the other page elements.

For example (problem situation):

<span id="lbl" style="width: 100px"></span>

Things were working absolutely fine untill our tester entered a long string value for this without spaces in it (for e.g. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa).

To our surprise, the width property was suddenly not working and the result was that the displayed label now exceeded the given restriction of 100px.

Every one doing web-development have or will encounter this problem some time in their life.

So, the question: how to solve this issue, or in other words how to wrap continuous text in html?

Answer: use the css style

word-wrap: break-word;

For example (solution):

<span id="lbl" style="width: 100px; word-wrap: break-word;"

Mention this css style in any of your container html tags and you can Rest In Peaaaccccceeeee !!

Goodbye 2012

The WordPress.com stats helper monkeys prepared a 2012 annual report for this blog.

Here’s an excerpt:

600 people reached the top of Mt. Everest in 2012. This blog got about 4,700 views in 2012. If every person who reached the top of Mt. Everest viewed this blog, it would have taken 8 years to get that many views.

Click here to see the complete report.

See you in 2013. Happy New Year !!

Script to shrink MS SQLServer log files

Clean DatabaseWe regularly face this problem on our development server where in due to limited disc space, the hard-drive space starts screaming out loud with the message “low disk space”.

The one big space hungry giant in this regard, if you are using Microsoft SQLServer, is the log files that the databases in SQLServer maintains; and it is found that to most users the information contained in these log files is of no use at all.

So then below is the script to be executed under MS SQLServer that would shrink the size of the log files for each database under a given server, and free up considerable amount of your disk space (at times a lot of space if you are using sql-server since a long time and haven’t executed this clean up since a considerable time period)

For SQL Server 2005:

declare @ssql nvarchar(4000)
set @ssql= '
if ''?'' not in (''tempdb'',''master'',''model'',''msdb'') begin
use [?]
declare @tsql nvarchar(4000) set @tsql = ''''
declare @iLogFile int
declare @sLogFileName varchar(55)
declare LogFiles cursor for
select fileid from sysfiles where status & 0x40 = 0x40
open LogFiles
fetch next from LogFiles into @iLogFile
while @@fetch_status = 0
begin
set @tsql = @tsql + ''DBCC SHRINKFILE(''+cast(@iLogFile as varchar(5))+'', 1) ''
fetch next from LogFiles into @iLogFile
end
set @tsql = ''USE [?]; '' + @tsql + '' BACKUP LOG [?] WITH TRUNCATE_ONLY '' + @tsql
--print @tsql --uncomment this for debugging purpose
exec(@tsql)
close LogFiles
DEALLOCATE LogFiles
end'
exec sp_msforeachdb @ssql

For SQL Server 2008:

declare @ssql nvarchar(4000)
set @ssql= '
if ''?'' not in (''tempdb'',''master'',''model'',''msdb'') begin
use [?]
declare @tsql nvarchar(4000) set @tsql = ''''
declare @iLogFile int
declare @sLogFileName varchar(55)
declare @RecoveryModel nvarchar(10)
declare LogFiles cursor for
select fileid from sysfiles where status & 0x40 = 0x40
open LogFiles
fetch next from LogFiles into @iLogFile
while @@fetch_status = 0
begin
set @tsql = @tsql + ''DBCC SHRINKFILE(''+cast(@iLogFile as varchar(5))+'', 1) ''
fetch next from LogFiles into @iLogFile
end
select @RecoveryModel = CONVERT(nvarchar(10),Databasepropertyex(name, ''Recovery'')) from master..sysdatabases where name = ''?''
set @tsql = ''USE [?]; '' + @tsql + '' ALTER DATABASE [?] SET RECOVERY SIMPLE '' + @tsql
set @tsql = @tsql + ''; ALTER DATABASE [?] SET RECOVERY '' + @RecoveryModel + '';''
--print @tsql --for debugging
exec(@tsql)
close LogFiles
DEALLOCATE LogFiles
end'
exec sp_msforeachdb @ssql

Note: for those who don’t know where to run this script ==> open your sql server management studio, under that click on “new query”, paste the script, and hit execute.

Happy Cleaning !!

Pass custom information to sharepoint timer job

SharePoint TimerToday while creating a new sharepoint timer job, I came across this requirement to use the SPWeb on which the timer would execute upon. Now as usual I wrote the code considering SPContext.Current.Web. But on execution.. Booooom.. it crashed, and the reason ==> SPContext.Current.Web is not available when running a timer job.

Also, on initializing an instance of this timer job, one of the parameter that it takes is the instance of web-application. But even that is not useful as the current site can be any one of the various sites under the passed web-application.

So then the search started to find out a way to get current SPWeb during timer job execution.

After a lot of search, I came up with the following solution:

While initializing the timer job (usually during feature activation), the timer job instance has a property bag attached to it, accessible through:

<timer job instance>.Properties

This as usual is a collection of key and value pairs taking objects for both key and value, which means we can have anything as key and any object as its value.

So here is the answer then, which is: we can pass any custom information to a sharepoint timer job, during its instantiation, through the “Properties” property bag attached to the instance, and while its execution, the same values can be retrieved from the same property bag (through this.Properties[<key>]).

In my particular case, I passed the SPWeb’s url, on which the timer job feature was activated, as a value in the property bag, and while execution (in timer job’s execute method) that same value was retrieved back using this.Properties[<key name>].

Though I have mentioned the whole case in regards to knowing current SPWeb, but the solution can be used for passing any custom information to an instantiated sharepoint timer job.

“Updates are currently disallowed on GET requests” error trying to access web-application settings in Sharepoint Central Admin

SharePoint ErrorSuddenly today while trying to set “Resource Throttling” settings for one of our web-applications (from Central Administration -> Application Management -> Manage web applications -> select your web-application -> under General settings ribbon option -> Resource Throttling), sharepoint started showing error screen with  following error message:

Updates are currently disallowed on GET requests. 
To allow updates on a GET, set the 'AllowUnsafeUpdates' property on SPWeb

When googled for this error, most of the initial solutions point to some sharepoint code and related problems. But none of them gave satisfactory resolution for this central administration related issue.

Initially it seemed that we had left AllowUnsafeUpdate on our site to true. But even after setting it to false (through code) we kept on getting the same error.

Finally, we got the resolution here.

The solution is in the form of a power-shell script as below:

$w = get-spwebapplication <url of your sharepoint web-application>
$w.HttpThrottleSettings
$w.Update()

Run this and you should see the central administration settings back for use !!

“Extract / Get / Copy” DLL from “windows assembly folder / GAC / Global Assembly Cache”

DLL IconAt times we face a situation were in we can see a dll in the assembly listing (available at “c:\windows\assembly”) of windows and want to copy that dll. But you right click on an available dll and end up finding out that windows does not provide functionality to copy any dll from its assembly listing view.

So the Question is:

How to copy any dll available in “assembly” listing on windows machine? In other words how to copy any dll installed in GAC (Global Assembly Cache)

Solution:

  1. Open “run” OR write in “Search programs and files” box available at bottom of the window that appears when you click the windows button (Windows 7 and above specific).
  2. Write “%windir%\assembly\GAC_MSIL” in it
  3. Hit enter
  4. The window that appears shows the internal view of GAC where in you can find all dlls that appear under assembly listing
  5. Find the folder for the dll that you want to copy and under that you should find the required dll file

Mission Accomplished !!

Get text value from SharePoint’s RichTextField control

SharePoint RichTextBoxSharePoint’s RichTextField is a great control to provide our users with all the gorgeous formatting facilities on their entered text.

But there is a difference in the way you fetch the user entered value in your custom code. All SharePoint WebControls dealing with text have “Value” and “Text” property and so is the case with RichTextField control. Now you can use these properties to assign text to our RichTextField control, but the same properties do not provide us back the user entered value, and rather always gives back null.

So then the question is how to get value of RichTextField control? The answer is, lets say your RichTextField control variable is named myRichTextField, then use the following code property to fetch that control’s text value:

myRichTexField.HiddenInput.Value

Delete item working from ribbon but giving access denied from context menu in SharePoint 2010

SharePoint Access Denied DialogSharepoint provides two ways a user can delete an item from any list:

  1. From “Delete Item” menu option available in ribbon
  2. From “Delete Item” menu option available in the item’s context menu

Now you may think that both these options are just alias of one another, i.e. do the same thing the same way which is to delete the item, and must be implemented the same way.

But that is not the case. Both are implemented differently, i.e. both these options use different route of accessing the delete functionality on server. The context menu option uses remoting where as the ribbon option doesnot. So due to this, though you may have given “Delete Items” permission on the list, you need to provide one more permission, “Use Remote Interfaces”, to allow successful deletion from delete item option available from an item’s context menu. Not providing this second permission would lead to a condition where in the user would be able to delete items from “Delete Items” link available in Ribbon, but trying to delete an item from that item’s context menu would lead to an “Access Denied” error message.

Thus, when ever you find yourself into the situation where in the delete from ribbon is working but the same from context menu is giving error, go to the permission level that apply to the list or that item, provide “Use Remote Interfaces” permissions, MISSION ACCOMPLISHED.