Before we move to the generation part, let's talk about your html...
<p>
<!-- questionSection -->
<div class="alert alert-info" >
<strong style='color:#000000'>question</strong>
</div>
</p>
<p>
<!-- answerSection: correct -->
<p style='margin: 10px 0px 5px 400px;'>The correct answer was:</p>
<div class='alert alert-success review-correct'>
<strong>good answer</strong>
</div>
<br/>
You had selected: <span style='color:#a94442'>bad answer</span>
<!-- answerSection: wrong -->
<p style='margin: 10px 0px 5px 400px;'>Your correct answer:</p>
<div class='alert alert-success review-correct'><strong>qwe</strong></div>
</p>
<p>
<!-- reviewSection -->
<!-- ForQuiz(quiz) -->
</p>
<p>
can only nest phrasing content. <div>
and <p>
both belongs to flow content and palpable content. Therefore, you can't nested these 2 under <p>
element. For the definition of a phrasing content consult this answer.
- Personally, I would prefer using
<p>
to separate block of text, instead of using a <br />
to insert a line-break.
<!-- Question Section -->
<div class="alert alert-info" >
<strong style='color:#000000'>question</strong>
</div>
<!-- Answer Section: correct -->
<p style='margin: 10px 0px 5px 400px;'>The correct answer was:</p>
<div class='alert alert-success review-correct'>
<strong>good answer</strong>
</div>
<p>You had selected: <span style='color:#a94442'>bad answer</span></p>
<!-- Answer Section: wrong -->
<p style='margin: 10px 0px 5px 400px;'>Your correct answer:</p>
<div class='alert alert-success review-correct'>
<strong>the answer</strong>
</div>
<!-- Review Section -->
<!-- ForQuiz(quiz) -->
As for html generation, I believe, it is better to use a templating engine, such as RazorEngine which allows you to write C# code within the template itself :
review.cshtml :
@{
var correctAnswer = Model.Answer.GetText();
var userAnswer = Model.UserAnswer == null ? Model.UserAnswer.GetText() : string.Empty;
}
<!-- Question Section -->
<div class="alert alert-info">
<strong style='color:#000000'>@Model.Question.GetText()</strong>
</div>
<!-- Answer Section -->
@if (userAnswer == correctAnswer)
{
<p style='margin: 10px 0px 5px 400px;'>The correct answer was:</p>
<div class='alert alert-success review-correct'>
<strong>@correctAnswer</strong>
</div>
<p>You had selected: <span style='color:#a94442'>@userAnswer</span></p>
}
else
{
<p style='margin: 10px 0px 5px 400px;'>Your correct answer:</p>
<div class='alert alert-success review-correct'>
<strong>@correctAnswer</strong>
</div>
}
<!-- Review Section -->
<!-- TODO: implement ForQuiz(quiz) in razor syntax... -->
generation code :
public string GetReview(Quiz quiz)
{
var path = Desktop.GetFile("review.cshtml"); // TODO: fix this path
var template = File.ReadAllText(path);
return Engine.Razor.RunCompile(template, path, typeof(Quiz), quiz);
}
EDIT: I noticed you used the null-propagation operator from c# 6. You can also use the new string interpolation to format the html :
public static string GetReview3(Quiz quiz)
{
var builder = new StringBuilder();
builder.Append($@"
<div class='alert alert-info'>
<strong style='color:#000000'>{quiz.Question.GetText()}</strong>
</div>
");
string correctAnswer = quiz.Answer.GetText();
string userAnswer = quiz.UserAnswer?.GetText() ?? string.Empty;
if (correctAnswer == userAnswer)
{
builder.Append($@"
<p style='margin: 10px 0px 5px 400px;'>The correct answer was:</p>
<div class='alert alert-success review-correct'>
<strong>{correctAnswer}</strong>
</div>
<p>You had selected: <span style='color:#a94442'>{userAnswer}</span></p>
");
}
else
{
builder.Append($@"
<p style='margin: 10px 0px 5px 400px;'>Your correct answer:</p>
<div class='alert alert-success review-correct'>
<strong>{correctAnswer}</strong>
</div>
");
}
builder.Append(ForQuiz(quiz));
return builder.ToString();
}
HtmlTextWriter
class for this purpose. – Michael Brandon Morris Jun 14 at 14:28