Category: Patterns and practices

  • Page Layout not shown in Design Manager

    Page Layout not shown in Design Manager

    If you have created a custom page layout from Design Manager, it will have an .html extension.  When this file is uploaded to the _catalogs/masterpage gallery, an event receiver will convert the file to a matching .aspx page layout.

    However, I found a case where the .html file will not show in the Design Manager as you would expect.

    I’ve been using the Patterns and Practices console application method for deploying branding assets, and it is a great way to push your branding related files up to a target SharePoint site.  However, in the UploadPageLayout() method, it is assigning all files that are uploaded with the Page Layout content type.

    If you use this against a .html file, it will upload fine, and will generate the .aspx file, but the .aspx will not be published, and the page layout will not be shown in Design Manager.

    I’ve adjusted the SetPageLayoutMetadata() method as shown below to properly set the .html file with the Html Page Layout content type, which will allow it to be seen in the Design manager – as well as ensuring that the corresponding .aspx is published.

    private static void SetPageLayoutMetadata(Web web, File uploadFile, string title, string publishingAssociatedContentType)
    {
      var parentContentTypeId = "0x01010007FF3E057FA8AB4AA42FCB67B453FFC100E214EEE741181F4E9F7ACC43278EE811"; //Page Layout
    
      if(uploadFile.Name.ToLower().Contains(".html")) {
        parentContentTypeId = "0x01010007FF3E057FA8AB4AA42FCB67B453FFC100E214EEE741181F4E9F7ACC43278EE8110003D357F861E29844953D5CAA1D4D8A3B"; //Html Page Layout
      }
    
      var gallery = web.GetCatalog(116);
      web.Context.Load(gallery, g => g.ContentTypes);
      web.Context.ExecuteQuery();
    
      var contentTypeId = gallery.ContentTypes.FirstOrDefault(ct => ct.StringId.StartsWith(parentContentTypeId)).StringId;
      var item = uploadFile.ListItemAllFields;
      web.Context.Load(item);
    
      item["ContentTypeId"] = contentTypeId;
      item["Title"] = title;
      item["PublishingAssociatedContentType"] = publishingAssociatedContentType;
    
      item.Update();
      web.Context.ExecuteQuery();
    }
    
  • For the love of Pete make your error message meaningful!

    While debugging some custom SharePoint code (not written by me, mind you) today I ran in to this little gem:

    Cannot complete this action.

    Please try again. at Microsoft.SharePoint.Library.SPRequest.MapUrlToListAndView(String bstrUrl, String bstrUrlToMap, Guid& pgListId, Guid& pgViewId)
    at Microsoft.SharePoint.SPWeb.GetListFromWebPartPageUrl(String pageUrl)
    at Microsoft.SharePoint.SPWeb.GetListFromUrl(String pageUrl)
    at MyWebPart.EventCalendars.EventCalendars.GetCalendarUrl(Uri current, Uri referrerUri)
    at MyWebPart.EventCalendars.EventCalendars.CreateChildControls()

    Microsoft is a multi-billion dollar company.  And yet, with all their resources, training, skills and expertise, they still produce an error message that says the equivalent of “I’m broken. Try pressing F5 and see if I am not broken in a few seconds.”

    Is it really that the developers of the SPRequest object in this case don’t actually know what went wrong, so they bubble up this shoulder shrug?

    Or is it that they do know what went wrong, but are embarrassed by it?  Disgusted by it?  Too polite to throw another team under the bus publicly by immortalizing them in an Exception message?

    Who knows.

    Consequences

    When a developer encounters a message like this, the clock begins to tick while a solution is sought out.  With few clues as to what went wrong, that developer has to do more work to find a suitable repair.  More work means more time, more cost, more risk in the project.

    Microsoft can be blamed for project overruns, but they can’t be held directly responsible.  Still, as a standard bearer for the industry, I think they have an obligation to demonstrate the kinds of best practices they advocate.  This error message fails that test with great glory.

    We can do better

    The takeaway lesson here is obviously that if you or your company is creating a consumable API, provide useful feedback.  There’s a little bit of the Golden Rule tied up in this as well – write exception messages for others the way you’d want them to write a message for you.

  • A basic deployment process for web apps

    Ah, deployment. That nervous moment when you release your code in to the wild to be used by, well, users.  You’ve done your part to test it yourself.  You’ve maybe even had a QA team or engineer take their best shot at finding bugs.  And now it’s time to kiss that baby good bye and promote it to the all grown up world of “Production”.

    Having a good strategy for deployment does two things.  First, a good repeatable process will ensure that anybody on the team should be able to issue a release.  This is important purely so you don’t get that call while you’re waiting in line at Sea World telling you that an emergency patch is needed and you have to guide the team through the release.  Secondly, a good deployment is prepared for the awful but very possible reality that you might have to abort the release and roll back to the current version.

    That said, here is a basic structure I use for preparing and deploying code.

    Get a clean build.
    This can come either from a build server, continuous integration platform, or a reliable developer’s system.  I primarily use Visual Studio, so I always Clean and Rebuild at the Solution level to ensure all the assemblies are refreshed.

    Create a label or tag to mark your code.
    For me, this is a basic audit trail so I have a timestamp of the release candidate version.  It also is a milestone from which I can merge to a Production branch if this release is the final version that goes live.

    Create your release package.
    Again, the actual packaging of your release can take several forms.  For some projects I use the Visual Studio ‘Publish’ feature, and have it output to the file system.  From there I’ll FTP the files to the production destination.  For other projects, we use a Setup package that creates an Installer.  This is mostly used when someone else such as a client is performing the deployment.  Pick a method that makes the most sense for your product, team, and production environment, and stick with it.

    Establish your release schedule.
    I tend to favor Friday night as a deployment timeframe mostly because it gives you the weekend to address any issues that may arise (when dealing with a business or corporate application).  Some of my clients do releases on Thursday mornings, others on Thursday nights.  There really is no right answer here, so again, find the most suitable time for your team and users and make it predictable.

    Put up a maintenance page.
    Depending on the size and effort required to execute the deployment, it may be necessary to put up a maintenance page informing visitors to your site that you’re making updates.  What you don’t want is people thinking your app is broken because they stumble upon it while your trying to release fixes or new features.  I love the ‘app_offline.htm’ file that IIS can use to show a maintenance page.  It’s simple, easy to customize, and is easy to turn off and on as needed.

    Back up code.
    Pulling a back up of your code pre-release is the contingency plan in case a rollback is needed.  It may or may not be necessary to back up every file, particularly if you have static or user-contributed content.  Ditto that for any log files that may be in your app.  But certainly the ‘guts’ of your app (meaning .DLLs, include files, etc.) and the ‘skin’ of your app (meaning any UI elements).

    Back up data.
    In many cases, if you have nightly database backups running, then the prior successful backup may be sufficient.  However, for highly transactional or critical data systems you may need to do an explicit data backup during your release window.

    Deploy code.
    FTP files across, or run the installer.

    Deploy data changes.
    Execute any database changes that are necessary using your database administration tool.

    Confirm.
    Confirming a successful release may simply mean checking a status page, or logging in and running through a series of transactions.  Your QA process will dictate what is required to verify a release in the production environment.

    Take down maintenance page.
    Rename the app_offline.htm file or otherwise set your app to live mode.

    Branch or merge in to Production code line.
    Now that you’re in Production, create or update a Production code branch with the code versions that have just been deployed so that you can address any production bugs without interfering with your ongoing development process.

    Announce your updates.
    In some form or another, let your users know what’s changed.  This might be a blog post, a status update, Tweet or email.  You’ve worked hard on this code and these features, so use this as a chance to get your users excited about using it.

    The process of releasing code to production will obviously vary according to the nature of your app, your user community, and your hosting or production environment.  But having a defined process will help make each release go smoother.

  • Why every app should have a status page.

    Many years ago, after receiving a promotion, I finally was able to accomplish a goal I had set out for myself.  I bought a BMW.  The 10 year old 325i the car I had fallen in love with and was now in a position to acquire.

    One of my favorite features of the car was a small collection of red lights positioned above the windshield.  Every time you’d start the car, these lights would all come on, then one by one they’d go out.  Each light corresponded to a certain system or status check being run.  If a light stayed lit, it meant you might have a tail light out, or be low on windshield washer fluid.  It was, in my view, one of those elegant demonstrations of German engineering.

    As a developer, getting status on a system is a fundamental part of ensuring proper behavior, diagnosing issues, and validating assumptions.  And so I have come to always ensure that the apps I develop have a status page, and I encourage you to do so as well.

    There are some essential things to check:

    1. Can I connect to the database?
    2. Can I upload a file and/or write to the file system?
    3. Can I connect to external services or APIs?
    4. Can I send an email?

    Here is a sample from one of my projects.  You can see it runs through a series of checks, and shows results, response times, and any messages or alerts.

    Here’s the same page after I force an error.

     

    Your status page can be as detailed or general as you need.  What is important is to give yourself or your team enough information to make a decision or solve a problem.

    A few other things to consider –

    1. If your status page would contain sensitive information, be sure to properly mask or protect it.  It may or may not be feasible to put the status page in an area of your app that requires authentication, because if that authentication fails, you could never see the page.  But giving it an obscure Url or restricting its view to certain networks may be reasonable measures.

    2. Be sure to update your status page as you add features or new integration points to your app.

    3. Including a version number for your app is especially helpful when diagnosing problems.

    How are you or your team using status pages?  What must-have checks do your pages contain?

  • Writing meaningful comments and making your team happy.

    Perhaps not the most debated topic among developers, but one that is certainly on the list, is how, when and why to put comments in to code.

    One side argues that leaving comments and clues is a reasonable courtesy for the poor sap who inherits your code after you are long gone.

    The other side claims their code is so beautifully written and self-explanatory that no annotations are required.

    In my daily work, there are four places where commentary is possible:

    1. In the code itself
    2. On source control commits
    3. On bug reports or user stories
    4. On invoice time records

    All of these contexts have different levels of necessary comments, and different purposes (and consequences) tied to those comments.

    Inline comments

    By far the most common form of inline comment I use is to reference a bug ticket.  Whatever bug tracking or work item system you use, it probably assigns a nice integer to each item.  So when you fix that bug, you can notate the bug that is behind the change.

    //24549 send manual refund email if needed
    if (manualRefunds.Count > 0)
        SendManualRefundEmail(currentStudentTestEvent, manualRefunds);

    These comments make it trivial to find all the changes associated with a bug fix, simply by doing a search for the bug id.

    Another rule for inline comments is when, for whatever brilliant reason, a non-intuitive decision is made and implemented in code.  These comments are what make your code ‘senile-proof’.  What I mean by that is that we should just admit we can’t remember everything, and whether for our own sake or for the sake of our team, we need to record what we were thinking when we coded that magic number or unusual sequence.  Other times, we just point out the obvious.

    //2011-01-11:DMS - retrieve event to get test method
    Model.OpenTestEventSearch openTestEventSearch = TestEventBL.GetOpenTestEventSearch(studentTestEvent.TestEventID)
      .Where(o => o.TestGradeID == studentTestEvent.TestGradeID)
      .FirstOrDefault();

    Source Code Commits

    Checking code back in to the repository is a historic event.  In doing so, your code (working or not) is forever committed.  Just like any other monument, it’s nice to put a little plaque up to commemorate the event.

    In most cases, a commit will follow a bug fix, in which case your commit comments should also include the bug ID and a brief description of the fix.

    In other cases, you did something else, such as adding comments (!) or merged a code branch.  In those cases, a brief note about the change will help others on the team know why in the world you committed.

    Bug ticket closure

    In many (all?) bug tracking systems, when a case is resolved, the user has the opportunity to submit an update to the case.  Again, these notes can be concise, and can reference back to the revision or changeset in source control in which the code changes occurred to clear the case.  The level of detail required depends a lot on the other users of the bug tracking tool.  If end users will get updated upon the case closing, and they want an explanation of the fix, then you should give it to them.  However, if only project managers see it, and they are satisfied with a simple note saying “fixed in DEV branch”, then by all means, save the keystrokes.

    Time entries

    As a consultant, everything I do is tied to a time entry that ultimately ends up on an invoice to a client.  Therefore, when comments are put on time entries, they need to be ‘client friendly’.  In our case, however, the time entry is associated to a bug or work item, which has already been annotated, so the level of detail required is slightly less on the invoice.

    As all developers do, when we inherit someone else’s code, we are thankful for the information left for us by our predecessors.  It’s only reasonable to return the favor for those who come after us.

    What are your rules for commenting?  Add your thoughts below.

  • Datasets are not Business Objects.

    Programmers are notoriously stricken with pride when it comes to the design and coding of a solution.  Inevitably, each developer will believe that their particular approach is a) right, b) best, and c) unworthy of scrutiny.  I certainly am guilty of this kind of thinking.

    Thus, often established patterns or best practices fly in the face of the individual developer’s “I know best” mentality.  We rationalize our approach, and invent reasons why it’s better than the industry adopted standard or recognized method.  Consequently, we miss out on the benefit of the collective skills, experience and talent of the larger development community, and our products suffer from the unsupportability of highly idiosyncratic code.

    I use this preface to provide context to the following rant about a trend often seen in .NET development: using DataSets as business domain objects. 

    Object oriented programming has its strength in being able to accurately describe an piece of the world in a way that is predictable and reliable.  More recently, the separation of an object definition (that is, its properties) and object manipulation (that is, methods that operate on an object) has brought forth the trend to have distinctly define domain classes.

    A DataSet, while a suitable container for values pulled from a database table, is not a distinctly defined domain class.  It lacks structure, strong typing, and predictability.  Yet, it is an easy shortcut to connecting our application data to a set of business rules.

    Here are my objections to using DataSets in the place of Domain Objects:

    1. They are unpredictable. 

    Since a DataSet is based on the results of a query, it may at any point in time contain different fields even though it is named the same.  For instance, if two different stored procedures are used to retrieve a Customer record, but one has more (or less) fields selected, then I as a consumer of that data cannot reliably know what fields are available to me.  Does the query return First Name and Last Name, or does it concatenate them together as Full Name?  I don’t know until I try to reference a field that doesn’t exist.

    Contrasted with a Domain Object that explicitely defines the values for a business entity, such that I can always know what values are available to read or write, a DataSet inevitably leads to exception based development.

    2. They are not strongly typed.

    When I define a Domain Object, I explicitly declare each field and its data type.  If I try to assign a value that doesn’t match, I get an exception.  There is an intrinsic level of control that accompanies the strong typing of a well written Domain object.  A DataSet, however, is not explicitly typed. 

    3. They are undocumented.

    In writing a Domain object class, at least with .NET, I have the opportunity to annotate my properties with API style documentation that will be immediately available to any consumer of that class via the Visual Studio IDE.  I can tell my fellow developers about any nuances or rules affecting that class.  Further, the Visual Studio Intellisense auto-completion mechanism will allow a developer to see all of the properties available for that object. 

    A DataSet is a dumb container.  When I ask for a value from the DataSet, it gives me no context, guidance or insight to what that value is or represents.

    To be fair, a DataSet is certainly useful for in-memory representations of data.  But they fall flat when it comes to accurately modeling a domain or representing an entity.

    Here is some additional commentary on this topic from people far more qualified to expound on the details of this discussion.

  • Simple API Documentation guidelines

    This month’s issue of MSDN Magazine had a great article from Peter Gruenbaum titled A Coder’s Guide to Writing API Documentation.  Let’s face it, documentation of the code we write is typically an afterthough, rarely given the attention it deserves, and is the first thing we point to (when it is lacking, that is) to complain about the ramp up time required for supporting a system.

    I particularly liked one table Peter included in his article that laid out some basic guidelines for structuring documentation according to the type of code snippet we are annotating.  I think by following these simple guidelines, any developer can have a big impact on their codebase.

    Type Guideline Examples
    Class Start with a word like “Represents” “Represents a user’s photo album.”
    Methods and functions Start with a verb “Returns the number of contacts for the specified area.”

    “Pauses the video.”

    Properties Use a noun or start with verbs such as “Gets” or “Gets and sets” “The user’s tasks.”

    “Gets and sets a collection of the user’s tasks.”

    Events Start with a phrase such as “Raised when” or “Occurs when” “Raised when the response from server is received.”
    XML elements Use a noun-based phrase “The city’s postal code.”
    Boolean values For Boolean properties, start with “Indicates whether”; for Boolean return values on methods and functions, start with “Returns whether” “Indicates whether the control is visible.”

    “Returns whether two regions intersect.”

    I am a well documented fan and stickler for good commenting in code.  I have been in too many organizations that refuse to make time or priority to do the necessary effort, but then love to complain when it isn’t sufficient.  By using these basic guidelines, it seems reasonable that at least every public class, property and method can carry some descriptive notes that will aide the next developer who consumes those assets.

    Start small, and I’m sure you’ll find that it has a big impact later on.  Future ranks of developers who inherit your code will undoubtedly thank you for your diligence.