Archives for the month of: June, 2016

An issue we recently experienced with our SharePoint 2010 document sharing site had to do with List Item ECB Context Menu hover positioning on large document libraries that required you to scroll down to see all items.  When you hover over a list item, the expected behavior is that the context menu would be displayed to the right of the document title, and this is the case for the most part, until you have to scroll down to see a document.  Then when you hover over the item, the context menu appears farther up in the library, as depicted in the following example:

example

Not pretty.  Sad smile

Upon further research, I discovered that this had to do with the fact that SharePoint 2010 attempts to override default browser scrolling.  By reading the following blog article by Kyle Schaeffer, I was able to override SharePoint 2010’s default scrolling behavior, which in turn fixed the above SharePoint list item context menu positioning issue.

Thank you, Kyle!

Advertisements

Let’s face it.  There are times when a stored procedure is going to create a more efficient query, and provide the flexibility you need to return attributes from multiple SQL tables in a non-traditional way.

In my case, I had a number of different log tables that I wanted to combine into a single result.  My log tables contained different field attributes, and so I was not able to simply use the ObjectQuery<T>.Union method to combine my results.  It was much easier to simply create a stored procedure that could translate the information into a nice generic result from the combined tables.

It was this result that I wanted to work with, not the individual tables.  You can accomplish this in three easy steps:

1) Update your Model diagram (edmx) with the stored procedure you want to add.  (Update Model from Database –> Add –> Stored Procedure)

step1

2) Right-click on your diagram and choose Add –> Function Import.  Enter the name you want to use as the Entity function to retrieve the stored procedure.  Select the stored procedure you want to associate with this Entity Function.  Press Get Column Information.  Then select Create New Complex Type.  Enter the name of the custom Complex Type Entity you want to associate with the stored procedure.

step2

3) That’s it!  Now you can use the function in a very elegant way and still have a strongly typed object to work with.

step3

I recently went through the exercise of upgrading our internal SharePoint environment from 2007 to 2010.  Some of these sites were heavily customized and while we did experience our share of issues, all-in-all it was definitely not as painful as I initially predicted.  And I have to say that my favorite feature of SharePoint 2010 BY FAR is the ability to manage your SharePoint sites and lists using PowerShell.  I cannot adequately described how many times PowerShell has rescued me!

One issue we have had right off the bat had to do with a very large site collection used primarily for collaboration and document storage.  While the site collection was entirely made up of custom team sites, each created from a custom template (or now with SharePoint 2010 a custom solution), this site used a custom master page and is heavily branded.

The site collection contains thousands of sites, each containing multiple document libraries.  Now in SharePoint 2010, when a user attempts to upload a document, a popup dialog is displayed.  Because each of our documents contain a large number of metadata that are required based on the document type, the popup dialog form was long.  Perhaps as an unintended consequence of our branding, the popup dialog was cutting off the bottom part of the form, and our users were not able to successfully upload their documents.

dialog

The quickest way to resolve this is to go into Library Settings –> Advanced Settings, and in the Dialogs section, check No for “Launch forms in a dialog?”.

advancedsettings

By doing this, SharePoint will navigate to a full page to allow you to modify the document attributes.  Perhaps a little too much like SharePoint 2007, but definitely a lot less incident prone and an interface that our SharePoint users are a little more familiar with using.

fullpage

That solution is fine for one-off fixes, but I was faced with the daunting task of making this fix for thousands of document libraries in hundreds of sites.  Surprised smile

That’s where PowerShell comes in.  I was able to write a short little script in PowerShell that iterated all of the sites in my site collections, iterated all of the lists in each site, determined evaluate the document library’s current setting, and update the setting if necessary.

The setting is called NavigateForFormsPages and the value it stores is actually the opposite of what we check in the interface.  For example, if the value is set to False, then the Document Library will open a modal dialog, but if the value is set to True, then the Document Library will open a full page.  So in this case, we want to evaluate each Document Library and make sure the value is set to true.

# retrieve site collection database
# replace SP2010_DB_Content with your content database name
$db = Get-SPContentDatabase SP2010_DB_Content

# iterate all sites in the collection
$db.Sites | Get-SPWeb -limit all | ForEach-Object {

# iterate all lists in the sites
foreach ($list in $_.Lists) {

# evaluate NavigateForFormsPages advanced setting
# if the value is false, we want to set it to true

if (!$list.NavigateForFormsPages)
{
# output the site url, title, and NavigateForFormsPages
# for your record

Write-Host “$($_.url) – $($list.title) – $($list.NavigateForFormsPages)”

        # set the NavigateForFormsPages value to true
$list.NavigateForFormsPages = $true

        # update the list
$list.update()

        # output the site url, title, annd NavigateForFormsPages
# to make sure the value has changed

Write-Host “$($_.url) – $($list.title) – $($list.NavigateForFormsPages)”
}
}}

That’s it!  Smile

I ran into this issue with a heavily branded SharePoint site we recently upgraded to SharePoint 2010.  I noticed the branding elements were being included in the SharePoint dialog.

This is definitely not what we intended for our SharePoint dialogs.  Thankfully, SharePoint makes it easy to strip those elements out by adding the following class to any element you want left out:

<!– use s4-notdlg for any element you do not wish to include –>

Now our dialogs are much cleaner!  Smile

dialog2

Recently, after a patch was applied to the web server, some of our larger, more intensive applications starting throwing the following fairly cryptic exception:

ERROR: System.Web.HttpException: The URL-encoded form data is not valid.
System.InvalidOperationException:  Operation is not valid due to the current state of the object.

This is due to an update (MS11-100) that was pushed out in December 2011 that allows a web form to accept a limit of 1,000 items.

The fix is easy, simply add an item to your web.config appSettings section.  The following example increases the number of items accepted by a web form from 1,000 to 9,999:

<appSettings>
  <add key=”aspnet:MaxHttpCollectionKeys” value=”9999″ />
</appSettings>

So I had this strange issue today when I deployed an application that was designed in such a way that all of its javascript is stored in external .js files, as opposed to embedding it directly in the page.  I made some pretty heavy changes to the external .js files.

Everything worked great in both the local development environment and the staging environment.  But when I deployed to the production environment, the client-side functionality was not working properly.

I deployed and redeployed, but there was no change.  I looked at the javascript file on the production file system, and it reflected the changes.  But when I viewed the source of the javascript file in the web browser, I could see that none of my updates were reflected.

My first thought was to recycle the application pool, but that didn’t work.  Then I attempted to do an IISRESET.  That DIDN’T WORK either!!!

I went in and deleted my temporary internet files TWICE, and finally the updates were reflected.  I realize that javascript files are supposed to be cached, but I needed my changes to show up.

For the rest of the day, my users were complaining that the application was no longer working.  My instructions to delete the temporary internet files seemed to work in most cases, but I didn’t need my users to have to deal with that.

This is not an issue I typically deal with, because I usually embed my Javascript directly in the web page.  This is only an issue with script references to external .js files, and perhaps it is by design, because in most cases you want your external javascript references to be cached and load super fast!

I did some research and discovered that if you append the javascript file with a unique querystring, it will force the browser to retrieve the latest version of the file.  Some folks on the forums recommend appending the script reference with a date time value so that it is always unique, forcing the browser to always retrieve the latest version.

http://scripts/GMConsultantBench.js?version=%=System.DateTime.Now.ToString()%20%

I don’t fully agree with that approach, because for the most part, I want my .js files to cache. But I would like to control when an update occurs.

I recommend versioning your javascript so that for the most part it remains cache, but when you make an update, you can increment the version number to break through the cache just one time.

http://scripts/GMConsultantBench.js?version=1.0

Or, even better, you can set it to a unique GUID that you store in your web.config and just update the version in the web.config when you deploy an update.  Anyway, you get the idea!

I attempted to create an RSS in an MVC 2.0 application using my typical C# Web forms approach and received the following error:  OutputStream is not available when a custom TextWriter is used.

The main reason for this is that MVC Views assume the request will be in standard HTML and so it switches the TextWriter with its own writer.

The easiest way to get this done, then, is to handle the logic at the Controller level, rather than the View level.

1) First you will need to include a couple of libraries:

using System.Xml;
using System.ServiceModel.Syndication;

2) Then you want to create a custom RssActionResult, which the Controller will return:

public class RssActionResult : ActionResult
{
public SyndicationFeed Feed { get; set; }
public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.ContentType = “application/rss+xml”;

        Rss20FeedFormatter rssFormatter = new Rss20FeedFormatter(Feed);
using (XmlWriter writer = XmlWriter.Create(context.HttpContext.Response.Output))
{
rssFormatter.WriteTo(writer);
}
}
}

3) Then you want to set the Controller response to your custom result:

SyndicationFeed feed = new SyndicationFeed(
“IDEAInbox”,
“IDEAInbox Description”,
new Uri(“
http://IDEAInbox”),
“IDEAInboxSyndicationV1.0”,
DateTime.Now);
List<Idea> _Ideas = _myIdeaInboxservice.GetIdeas(-1, -1, 1);
List<SyndicationItem> items = new List<SyndicationItem>();
foreach (Idea _Idea in _Ideas)
{
SyndicationItem item = new SyndicationItem(_Idea.IdeaSubject,
_Idea.IdeaDescription,
new Uri(_Idea.Link),
“IDEAInboxIdeaID” + _Idea.IdeaID.ToString(),
_Idea.StatusInformation.CreateDateTime);
items.Add(item);
}
feed.Items = items;
return new RssActionResult() { Feed = feed };

I have an auto-generated entity framework Entity Data Model Designer File (edmx).  And while I am using Data Annotations for validation purposes, there are times when retrieving the maxlength of an entity property programmatically would be very useful.

image

In some cases, I may want to simply truncate the value, rather than throw an error if the maxlength of a property is exceeded.  Or I may want to surface the maxlength property to the client for client-side validation purposes.

It turns out to be a simple query, but it took me a while to find it.  You will need to reference the following libraries:

using System.Data.Objects.DataClasses;
using System.Data.Metadata.Edm;

This is the method to retrieve the MaxLength property.  Please note that you may get an exception if the property does not have a MaxLength property specified.

public static int? GetMaxLength(this EntityObject entityObject, string entityProperty)
{
CATDBEntities _context = new CATDBEntities();
int? result = null;
using (_context)
{
var q = from meta in _context.MetadataWorkspace.GetItems(DataSpace.CSpace)
.Where(m => m.BuiltInTypeKind == BuiltInTypeKind.EntityType)
from p in (meta as EntityType).Properties
.Where(p => p.DeclaringType.Name == entityObject.GetType().Name
&& p.Name == entityProperty
&& p.TypeUsage.EdmType.Name == “String”)
select p;

    var queryResult = from meta in _context.MetadataWorkspace.GetItems(DataSpace.CSpace)
.Where(m => m.BuiltInTypeKind == BuiltInTypeKind.EntityType)
from p in (meta as EntityType).Properties
.Where(p => p.DeclaringType.Name == entityObject.GetType().Name
&& p.Name == entityProperty
&& p.TypeUsage.EdmType.Name == “String”)
select p.TypeUsage.Facets[“MaxLength”].Value;
if (queryResult.Count() > 0)
{
result = Convert.ToInt32(queryResult.First());
}
}
return result;
}

To call this method, simply instantiate the entity object and pass in the proper parameters:

project _project = new project();
int? maxLength = DataAnnotation.GetMaxLength(_project, “project_name”);

I struggled a bit attempting to generate dynamic javascript in an MVC Razor page view.  I kept getting the following error:  Too many characters in character literal.

I did a little research and found the answer.  You will need to include
@using System.Text; at the top of your page view.

To build my javascript, I included the following code block within my <script> tags:

@{
StringBuilder sb = new StringBuilder();
foreach (GetBillingCodes_Result billingCode in Model.BillingCodes)
{
sb.Append(“AddBillingCode(‘” + billingCode.billing_code + “’”);
sb.Append(“, ‘” + billingCode.travel + “’”);
sb.Append(“, ‘” + billingCode.billing_code_type + “’”);
sb.Append(“, ‘” + billingCode.billing_rate + “’”);
sb.Append(“, ‘” + billingCode.taxable + “’”);
sb.Append(“, ‘” + billingCode.discount + “’”);
sb.Append(“, ‘” + billingCode.C100_club + “’”);
sb.Append(“, ‘” + billingCode.active + “’”);
sb.Append(“);”);
}
@MvcHtmlString.Create(sb.ToString());
}

In this new cyberworld saturated with abundant mouse clicks, it has become more necessary to try to get your user’s attention before allowing them to perform an action that may result in a critical error.  One of these actions is leaving the application without first saving changes.  In some cases, a request to leave a page without first saving changes may be on purposes, but in many cases it may have been the result of an accidental mouse click.

Browsers have provided a built-in prompt that warns users before leaving certain pages.  The user then has the option of leaving the page or staying on the page.  This built-in prompt is not at all flexible, by design, to prevent rogue sites from actually preventing users from leaving their web sites.

The following is an example of how you might implement this prompt using the window.onbeforeunload event.

STEP 1:  Mechanism to determine if there are unsaved changes
Because there is no reason to warn your users from leaving if they have not made any changes, the first thing you want to do is create a hidden field or client-side variable that specifies whether your page contains unsaved changes.

In this example, I have created a hidden input to store my change status:
@Html.Hidden(“UnsavedChanges”, “0”)

I then created a function to update the change status:
function HandleFieldChange()
{
$(“#UnsavedChanges”).val(“1”);
}

Finally, I used a little jQuery to easily add the field change event:
$(“input”).change(function(){
HandleFieldChange();
});
$(“select”).change(function(){
HandleFieldChange();
});
$(“textarea”).change(function(){
HandleFieldChange();
});
$(“input:checkbox”).click(function(){
HandleFieldChange();
});
$(“input:radio”).click(function(){
HandleFieldChange();
});

STEP 2:  Use the browser’s built-in warning prompt before leaving a page.

Again, this cannot be customized.  If it could, that would open the door for this functionality to be used maliciously.  You don’t have any control over how the warning looks, but you can insert a custom message into the prompt.

This function checks to see if there are unsaved changes.  If there are, it calls the browser’s built-in warning and inserts a custom message.

window.onbeforeunload = function() {
if ($(“#UnsavedChanges”).val() == “1”)
{
var _message = “You currently have unsaved changes!!!\n\nAre you sure you want to exit without saving.\n\nChoose ‘Leave this page’ to exit without saving changes.\nChoose ‘Stay on this page’ to return to the billing profile.”;
return _message;
}
}

RESULT

It’s not as pretty as I would like, but it works!

ieprompt.png