HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Monkeying around with Survey Monkey and Asp.Net Mvc

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
aroundsurveymvcwithmonkeynetandaspmonkeying

Problem

Intro

I've been a desktop dev for a long time now, and have never really had to monkey with web development until very recently. I have a need to do some custom integration with Survey Monkey's Api and as a "Hello World" I came up with this simple ASP.Net MVC app that queries Survey Monkey for a list of my surveys and displays some real basic info about them. (Nothing I couldn't get from just going to their site, but hey!, I'm learning here.)

I have no idea what I'm doing, so any and all feedback would be greatly appreciated. I'd be particularly interested in some way to cache the results from the API request so that I don't have to fetch it each time the page loads.
The Tech

  • C# 6.0



  • MVC 5.0



  • Ninject MVC for dependency injection.



  • Survey Monkey API wrapper for C#.



The Code

The API wrapper library needs an API Key & Token to connect to Survey Monkey. In order to keep them out of the GitHub repo, I created some environment variables and a factory class that knows how to access them and return an instance of SurveyMonkeyApi.
./SurveyMonkeyApiFactory.cs

namespace SurveyMonkeyPlayground
{
    public interface ISurveyMonkeyApiFactory
    {
        SurveyMonkeyApi Create();
    }

    public class SurveyMonkeyApiFactory : ISurveyMonkeyApiFactory
    {
        public SurveyMonkeyApi Create()
        {
            string apiKey = Environment.GetEnvironmentVariable("SM_APIKEY");
            string token = Environment.GetEnvironmentVariable("SM_TOKEN");

            return new SurveyMonkeyApi(apiKey, token);
        }
    }
}


Next I created a model that is a subset of the full Survey object from the 3rd party library.
./Models/SurveyModel.cs

namespace SurveyMonkeyPlayground.Models
{
    public class SurveyModel
    {
        public string Name { get; set; }
        public int ResponseCount { get; set; }
        public string Url { get; set; }
    }
}


And then a controller to handle requests for a list of all surveys, and details about any g

Solution

ASP.NET MVC will produce a controller instance for each request, so you need a bit of help from the framework to assist you with caching - because anything you cache at controller level will only live for a single request's lifetime. As always, Stack Overflow has answers for you :)

// GET: Surveys


// GET: Surveys/Details?name=SomeSurveyName


These comments are somewhat redundant. Unless you've massively changed how routing works in your application, the controller's name and each ActionResult method already says everything this comment says.

This part could use a more ...vertical layout. Note that when you're using C# object initializer syntax with a parameterless constructor (i.e. new SurveyModel() { ... }), the parentheses are redundant.

var surveys = surveyMonkey.GetSurveyList()
                          .Select(s => new SurveyModel 
                          {
                              Name = s.Nickname,
                              ResponseCount = s.NumResponses,
                              Url = s.AnalysisUrl 
                          });


Note that this result is deferring the instantiation of SurveyModel objects to the view, which iterates the surveys.

Same here:

var survey = surveyMonkey.GetSurveyList()
                         .Where(s => s.Nickname == name)
                         .Select(s => new SurveyModel
                         { 
                             Name = s.Nickname,
                             ResponseCount = s.NumResponses,
                             Url = s.AnalysisUrl
                         })
                         .First();


The .First() is a little bit confusing here. If the monkey API can only ever return 1 survey for a given name, .SingleOrDefault() would be a much better choice - it would be documenting the fact that a survey has a unique name, and it would return null when no match is found.

Note that .First() will throw an InvalidOperationException - "Sequence contains no element" if the API returns no item for the specified name.

Code Snippets

// GET: Surveys
// GET: Surveys/Details?name=SomeSurveyName
var surveys = surveyMonkey.GetSurveyList()
                          .Select(s => new SurveyModel 
                          {
                              Name = s.Nickname,
                              ResponseCount = s.NumResponses,
                              Url = s.AnalysisUrl 
                          });
var survey = surveyMonkey.GetSurveyList()
                         .Where(s => s.Nickname == name)
                         .Select(s => new SurveyModel
                         { 
                             Name = s.Nickname,
                             ResponseCount = s.NumResponses,
                             Url = s.AnalysisUrl
                         })
                         .First();

Context

StackExchange Code Review Q#97319, answer score: 6

Revisions (0)

No revisions yet.