0

I'm gonna cut to the chase. I'm creating a Survey platform, it has 3 models.

Model Survey, it has Many SurveyQuestion which has many SurveyAnswer. (I can insert all of the values of these models but I dont think it is needed)

public class SurveyAnswer
{
    [Key]
    public int Id { get; set; }

    public string Value { get; set; }

    public string SubmittedBy { get; set; }

    public int SurveyId { get; set; }

    public int QuestionId { get; set; }

    public virtual Survey Survey { get; set; }

    public virtual SurveyQuestion Question { get; set; }

    public string Comment { get; set; }

}

Now a problem I'm having is once someone created a survey and another person is starting it, he answers and that's it. How do I show that the next time he comes to an index page? How do I show that "you already submitted this survey"? Do I do that in Controller or in View? I would prefer to that in this action currently (it's a menu for all ongoing surveys).

    [HttpGet]
    public ActionResult Menu()
    {
        var survey = Mapper.Map<IEnumerable<Survey>, IEnumerable<SurveyViewModel>>(_unitOfWork.SurveyRepository.Get());
        return View(survey.ToList());
    }
  • I assume you are going to check if the user has already submitted by checking `SubmittedBy`: You can use composite uniqueness on multiple properties of the SurveyAnswer class as shown [here](https://stackoverflow.com/a/23090070/4636715). For your example, the `SubmittedBy` and `SurveyId` may build a unique key together, and that would be sufficient I guess. – vahdet Feb 27 '18 at 11:27
  • I assume `SubmittedBy` is the user who answered it? Cant you just query what surveys they have completed based on that value? –  Feb 27 '18 at 11:27
  • Yes SubmittedBy is the User and QuestionId are the most important. –  Feb 27 '18 at 11:28
  • @vahdet I think you can't create a unique key between a string and an int? –  Feb 27 '18 at 12:26
  • @HighSepton yes, you've got the point. – vahdet Feb 27 '18 at 13:01

2 Answers2

1

Put all your validation rules to your AbstractValidator class.

[Validator(typeof(SurveyAnswerValidator))]
public class SurveyAnswer{

[Key]
public int Id { get; set; }

public string Value { get; set; }

public string SubmittedBy { get; set; }

public int SurveyId { get; set; }

public int QuestionId { get; set; }

public virtual Survey Survey { get; set; }

public virtual SurveyQuestion Question { get; set; }

public string Comment { get; set; }

}

public class SurveyAnswerValidator : AbstractValidator<SurveyAnswer>
{
    public SurveyAnswerValidator()
    {
     //list your rules
     RuleFor(x => x.SubmittedBy).Must(BeUnique).WithMessage("Already 
     submitted this survey");
    }

    private bool BeUnique(string submittedBy)
    {
        if(_context.SurveyAnswers.
        FirstOrDefault(x => x.SubmittedBy == submittedBy) == null){
        return true;
        }
        else{
        return false;
        }

    }
}

If you want to check uniqueness in ViewModel you can use Remote.

public class SurveyAnswerVM{

[Key]
public int Id { get; set; }

public string Value { get; set; }

[Remote("HasSubmitted", "ControllerName")]
public string SubmittedBy { get; set; }

public int SurveyId { get; set; }

public int QuestionId { get; set; }

public virtual Survey Survey { get; set; }

public virtual SurveyQuestion Question { get; set; }

public string Comment { get; set; }

}

Where HasSubmitted is a method you may create in controller to return true if the user has submitted. RemoteAttribute https://msdn.microsoft.com/en-us/library/gg508808(VS.98).aspx

Indrit Kello
  • 1,293
  • 8
  • 19
0

The best solution by vahdet (suggested in comments)

 [Index("IX_AnswerQuestion", 2, IsUnique = true)]
    [StringLength(36)]
    public string SubmittedBy { get; set; }

    public int SurveyId { get; set; }

    [Index("IX_AnswerQuestion", 1, IsUnique = true)]
    public int QuestionId { get; set; }