public void Post(Guid pollId, ChoiceCreationRequestModel choiceCreationRequest)
        {
            using (IVotingContext context = _contextFactory.CreateContext())
            {
                if (choiceCreationRequest == null)
                {
                    ThrowError(HttpStatusCode.BadRequest);
                }

                Poll poll = context
                            .Polls
                            .Include(p => p.Choices)
                            .SingleOrDefault(p => p.UUID == pollId);

                if (poll == null)
                {
                    ThrowError(HttpStatusCode.NotFound, string.Format("Poll {0} does not exist", pollId));
                }

                if (!poll.ChoiceAdding)
                {
                    ThrowError(HttpStatusCode.MethodNotAllowed, string.Format("Option adding not allowed for poll {0}", pollId));
                }

                if (!ModelState.IsValid)
                {
                    ThrowError(HttpStatusCode.BadRequest, ModelState);
                }

                Choice newOption = CreateChoiceFromRequest(choiceCreationRequest);

                _metricHandler.HandleChoiceAddedEvent(newOption, pollId);

                poll.Choices.Add(newOption);
                context.Choices.Add(newOption);

                poll.LastUpdatedUtc = DateTime.UtcNow;

                context.SaveChanges();

                ClientSignaller.SignalUpdate(poll.UUID.ToString());
            }
        }
        public void Put(Guid pollId, Guid tokenGuid, BallotRequestModel ballotRequest)
        {
            using (IVotingContext context = _contextFactory.CreateContext())
            {
                if (ballotRequest == null)
                {
                    ThrowError(HttpStatusCode.BadRequest);
                }

                if (!ModelState.IsValid)
                {
                    ThrowError(HttpStatusCode.BadRequest, ModelState);
                }

                Poll poll = context
                            .Polls
                            .Where(p => p.UUID == pollId)
                            .Include(p => p.Ballots)
                            .Include(p => p.Choices)
                            .SingleOrDefault();

                if (poll == null)
                {
                    ThrowError(HttpStatusCode.NotFound, String.Format("Poll {0} not found", pollId));
                }

                if (poll.ExpiryDateUtc.HasValue && poll.ExpiryDateUtc < DateTime.UtcNow)
                {
                    ThrowError(HttpStatusCode.Forbidden, String.Format("Poll {0} has expired", pollId));
                }


                foreach (VoteRequestModel voteRequest in ballotRequest.Votes)
                {
                    if (poll.Choices.All(o => o.Id != voteRequest.ChoiceId))
                    {
                        ModelState.AddModelError("OptionId", "Option choice not valid for this poll");
                    }
                }

                Ballot ballot = poll
                                .Ballots
                                .SingleOrDefault(t => t.TokenGuid == tokenGuid);

                if (ballot == null)
                {
                    if (poll.InviteOnly)
                    {
                        ThrowError(HttpStatusCode.Forbidden, String.Format("Token {0} not valid for this poll", tokenGuid));
                    }
                    else
                    {
                        ballot = new Ballot()
                        {
                            TokenGuid = tokenGuid
                        };
                        poll.Ballots.Add(ballot);
                    }
                }

                // Poll specific validation
                IVoteValidator voteValidator = _voteValidatorFactory.CreateValidator(poll.PollType);
                voteValidator.Validate(ballotRequest.Votes, poll, ModelState);

                if (!ModelState.IsValid)
                {
                    ThrowError(HttpStatusCode.BadRequest, ModelState);
                }

                List <Vote> existingVotes = context
                                            .Votes
                                            .Include(v => v.Poll)
                                            .Where(v => v.Ballot.TokenGuid == tokenGuid && v.Poll.UUID == pollId)
                                            .ToList();

                foreach (Vote contextVote in existingVotes)
                {
                    _metricHandler.HandleVoteDeletedEvent(contextVote, pollId);
                    context.Votes.Remove(contextVote);
                }

                // For some reason, we don't have an addrange function on Entity Framework
                foreach (VoteRequestModel voteRequest in ballotRequest.Votes)
                {
                    Choice option = context
                                    .Choices
                                    .Single(o => o.Id == voteRequest.ChoiceId);

                    Vote modelToVote = ModelToVote(voteRequest, ballot, option, poll);
                    context.Votes.Add(modelToVote);

                    _metricHandler.HandleVoteAddedEvent(modelToVote, pollId);
                }

                if (!String.IsNullOrEmpty(ballotRequest.VoterName))
                {
                    ballot.VoterName = Regex.Replace(ballotRequest.VoterName, ValidVoterNameRegex, "");
                }

                ballot.HasVoted = true;

                poll.LastUpdatedUtc = DateTime.UtcNow;

                context.SaveChanges();

                ClientSignaller.SignalUpdate(poll.UUID.ToString());
            }
        }