Programming tutorials shows us a land of promise where everything happens as you think; as soon as you think. But real world doesn’t work that way most of the times. Here; you spend hours debugging some CORS error or thinking why your database table Id column is not auto-incrementing. For the last 2 days; I am participating in a coding interview which spans 2 days and these series of blog is based on that experience – what am I thinking at each stage; what is the issue and how I am resolving them. This is the fourth part of that.
Black cloud on the swagger front
When we tried to run the backend project; the swagger returned a 500 error.
Few things were missing in SurveyController.cs class –
1 [ApiController]
was missing before the
[Route("api/[controller]")]public class SurveyController : Controller
line and
2. [HttpGet] and [HttpPost] was absent before the method signatures; as I created the file from a wrong template.
Now after solving this issues; when we try to submit the survey form from the front-end; it is giving us 400 error. Yikes! Roaming around in the preview tab of browser; we can see the issue –
$.Questions[0].Answers[0].isCorrect: [,…]
0: "The JSON value could not be converted to System.Boolean. Path: $.Questions[0].Answers[0].isCorrect | LineNumber: 0 | BytePositionInLine: 80."
So; it failed to convert isCorrect from string to boolean.
So; we gave them a Boolean value. After that; all of the string value – title, text etc was expecting default value except null; and we had to make them uppercase as to match them with backend model. So the final ts file for survey looks like this that can post to the backend –
import { Component, OnInit } from '@angular/core';
import { FormArray, FormControl, FormGroup } from '@angular/forms';
import { HttpClientService } from 'src/app/http-client.service';
@Component({
selector: 'app-survey-add',
templateUrl: './survey-add.component.html',
styleUrls: ['./survey-add.component.scss']
})
export class SurveyAddComponent implements OnInit {
_client: HttpClientService;
surveyForm = new FormGroup({
Title: new FormControl(""),
Questions: new FormArray(
[
new FormGroup(
{
Text: new FormControl(""),
Answers: new FormArray(
[
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
]
)
}
),
new FormGroup(
{
Text: new FormControl(""),
Answers: new FormArray(
[
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
]
)
}
),
new FormGroup(
{
Text: new FormControl(""),
Answers: new FormArray(
[
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
]
)
}
),
]
),
});
constructor(client: HttpClientService) { this._client = client }
ngOnInit(): void {
}
getQuestionControls() {
return this.surveyForm.controls['Questions'] as FormArray;
}
getAnswerControls(question: any) {
console.log(question['Answers'] as FormArray);
return question['Answers'];
}
selectAnswer(i: number, j: number) {
}
save() {
this._client.postData("survey", this.surveyForm.value).subscribe((res) => {
console.log(res);
});
}
cancel() {
this.surveyForm = new FormGroup({
title: new FormControl(),
Questions: new FormArray(
[
new FormGroup(
{
Text: new FormControl(""),
Answers: new FormArray(
[
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
]
)
}
),
new FormGroup(
{
Text: new FormControl(""),
Answers: new FormArray(
[
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
]
)
}
),
new FormGroup(
{
Text: new FormControl(""),
Answers: new FormArray(
[
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
new FormGroup(
{
Text: new FormControl(""),
isCorrect: new FormControl(false),
}
),
]
)
}
),
]
),
});
}
}
We have to change our surveyRepository also to enable it to save survey, questions and answers.
The implementation that I go for is like this –
using dev_test.DTOs;
namespace dev_test.Repositories.Contracts
{
public class SurveyRepository : ISurveyRepository
{
public DatabaseContext _databaseContext;
public SurveyRepository(DatabaseContext databaseContext)
{
_databaseContext = databaseContext;
}
IEnumerable<Survey> ISurveyRepository.GetSurveys()
{
_databaseContext.Database.EnsureCreated();
return _databaseContext.Survey.ToList();
}
void ISurveyRepository.PostSurveys(SurveyComposite survey)
{
Survey surv = new Survey
{
Title = survey.Title
};
_databaseContext.Add<Survey>(surv);
_databaseContext.SaveChanges();
foreach(var ques in survey.Questions)
{
Question q = new Question
{
Text = ques.Text,
SurveyId = surv.Id
};
_databaseContext.Add<Question>(q);
_databaseContext.SaveChanges();
foreach(var ans in ques.Answers)
{
Answer answer = new Answer
{
QuestionId = q.Id,
Text = ans.Text,
IsCorrect = ans.IsCorrect
};
_databaseContext.Add<Answer>(answer);
_databaseContext.SaveChanges();
}
}
}
}
}
We forgot to update CreatedDate and UpdatedDate for survey; so this code is also throwing an error for that.
So; we change our Survey model creation like this –
Survey surv = new Survey
{
Title = survey.Title,
CreatedDate = DateTime.Now,
UpdatedDate = DateTime.Now
};
It’s still giving us – Invalid column name 'CreatedDate'.
Invalid column name 'UpdatedDate'.
The reason for this is in our db design. If we look closely; for all other two word terms; we used camel casing without any hyphen or underscore, like – isActive
; which is the right way. But for these 2 dates; we used all lower case with underscore in between, like created_date. So; C# can’t map CreatedDate
to created_date
.
So; we change our db design again and edit all word1_word2
format into camelCase
.
The code and updated scripts will be available at version_2.
This actually solves the issue of saving multiple users; multiple surveys and multiple question and answers.
But all we did is just created a skeleton to save some data.
And we have some issues here; for example –
- When saving the user with existing email; it throws an error; next time if we give different email; it saves correctly but skips an index in database.
- Saving successfully doesn’t do anything in the front end. It should give an success message or toast ad redirect to list page.
- The save method is returning only a boolean. It should be corrected to send correct format data.
- Validations are not handled properly.
- Survey page should be dynamic. It is bulky and unmanageable at this time.
- No interceptor to add header information
- We should have ideally separated the DTOs and models for the backend project.
- We didn’t go for either code first or db first approach. We need to change that (we are going to code first).
- No authentication and authorization is implemented.
- There are some other issues with the code.
We will start to fix all of these in the code version_3 and onwards.
Other episodes in this series:
First Part
Second Part
Third Part
Fourth Part
And the code is given is updated into –
Github