I am working on Website in which front end is developed in Angular 7 . I am sending an array from angular in json format to c# asp.net core. I am getting data in below format
`First = {"model": [{
"_organization_Name": "erw",
"_designation": "dfs",
"_p_Start_Date": "2019-02-28T19:00:00Z",
"_p_End_Date": "2019-03-27T19:00:00Z"
},
{
"_organization_Name": "erwfg",
"_designation": "dfsfgfg",
"_p_Start_Date": "2019-02-28T19:00:00Z",
"_p_End_Date": "2019-03-27T19:00:00Z"
}
]
}`
My Method in asp.net core below
[HttpPost("[action]")]
public IActionResult SaveProfessional([FromBody]JObject prof)
{
var obj = new Candidate_Professional_Info_Table(_context);
obj.Identity_Number = 112131.ToString();
obj =
JsonConvert.DeserializeObject<Candidate_Educational_Info_Table>(prof);
var result = obj.SaveProfessional(prof);
return Ok(new { suces = "result" });
}
My code is not deserializing json object Any solution please as now I have spend one week in this problem. My c# model is given below
public int ID { get; set; }
public string Identity_Number { get; set; }
[Required]
[RegularExpression("^[a-zA-Z0-9]+$", ErrorMessage = "Organization Name Not Valid")]
public string Organization_Name { get; set; }
[Required]
[RegularExpression("^/d{1, 2}///d{1,2}///d{4}$")]
public DateTime? p_Start_Date { get; set; }
[RegularExpression("^/d{1, 2}///d{1,2}///d{4}$")]
public DateTime? p_End_Date { get; set; }
[Required]
[RegularExpression("^[a-zA-Z0-9]+$", ErrorMessage = "Designation Name Not Valid")]
public string Designation { get; set; }
public bool InProgress { get; set; }
[NotMapped]
public List<Candidate_Professional_Info_Table> listprof { get; set; }
[NotMapped]
private readonly RegConnString _Context;
public Candidate_Professional_Info_Table(RegConnString connString)
{
_Context = connString;
}
You have underscores before your properties thats why the JsonConvert cannot map properly.
You can use [JsonProperty("")] attributes to map to the correct property
your properties would look like then
[Required]
[RegularExpression("^[a-zA-Z0-9]+$", ErrorMessage = "Organization Name Not Valid")]
[JsonProperty("_organization_Name")]
public string Organization_Name { get; set; }
[Required]
[RegularExpression("^/d{1, 2}///d{1,2}///d{4}$")]
[JsonProperty("_p_Start_Date")]
public DateTime? p_Start_Date { get; set; }
[RegularExpression("^/d{1, 2}///d{1,2}///d{4}$")]
[JsonProperty("_p_End_Date")]
public DateTime? p_End_Date { get; set; }
[Required]
[RegularExpression("^[a-zA-Z0-9]+$", ErrorMessage = "Designation Name Not Valid")]
[JsonProperty("_designation")]
public string Designation { get; set; }
To handle for the rest. You have a root object called model. But all we want is the List<Candidate_Educational_Info_Table>
public IActionResult SaveProfessional([FromBody]JObject prof)
{
//select the model itself. Also do some nullchecking to prevent errors if empty
var fooModel = prof.First;
//select the content of the model(your actual array). Also do some nullchecking to prevent errors if empty
var fooObjectArray= fooModel.First;
var theDeserializedList = fooObjectArray.ToObject<List<Candidate_Educational_Info_Table>>();
foreach (var item in theDeserializedList)
{
//handle the rest of what you want to do.
//As i see you inject the context into the objects on create but this will not be possible if you use the deserialze.
//Its better to pass the context on the method SaveProfessional
}
return Ok(new { suces = "result" });
}
There are a variety of JSON serializers. The one i usually use is Newtonsoft Json
Movie m = JsonConvert.DeserializeObject<Movie>(json);
You can also use dynamic deserilaization, which can deserialise without a class definition. You can use System.Web.Script.Serialization to parse and get a dynamic object. It also requires System.Web.Extensions reference
JavaScriptSerializer js = new JavaScriptSerializer();
dynamic modelItems = js.Deserialize<dynamic>(json);
var cors = new EnableCorsAttribute("http://localhost:4200", "*", "*");
config.EnableCors(cors);
.Linq;
namespace MTBCTest.Controllers
{
[EnableCors(origins: "http://localhost:4200", headers: "*", methods: "*")]
public class UsersController : ApiController
{
private testingDbEntities db = new testingDbEntities();
// GET: api/Users
[HttpGet]
public IQueryable<User> GetUsers()
{
return db.Users;
}
// GET: api/Users/5
[ResponseType(typeof(User))]
[HttpGet]
public IHttpActionResult GetUser(int id)
{
User user = db.Users.Find(id);
if (user == null)
{
return NotFound();
}
return Ok(user);
}
// PUT: api/Users/5
[ResponseType(typeof(void))]
[HttpPost]
public IHttpActionResult PutUser(User user)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
User ob = db.Users.Find(user.ID);
ob.FirstName = user.FirstName;
ob.LastName = user.LastName;
ob.Password = user.Password;
ob.EmailID = user.EmailID;
db.Entry(ob).State = EntityState.Modified;
db.SaveChanges();
return Ok();
}
// POST: api/Users
[HttpPost]
public IHttpActionResult PostUser(User user)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.InserUser(user.FirstName,user.LastName,user.EmailID, user.Password);
db.SaveChanges();
return Ok();
}
// DELETE: api/Users/5
[HttpGet]
public IHttpActionResult DeleteUser(int id)
{
User user = db.Users.Find(id);
if (user == null)
{
return NotFound();
}
db.Users.Remove(user);
db.SaveChanges();
return Ok();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool UserExists(int id)
{
return db.Users.Count(e => e.ID == id) > 0;
}
}
}
export class User {
public FirstName: string;
public LastName: string;
public EmailID: string;
public Password: string;
}
import { Injectable } from '#angular/core';
import { HttpClientModule, HttpClient, HttpHeaders } from '#angular/common/http';
import {User} from '../user';
import { Observable } from 'rxjs';
import { convertActionBinding } from
'#angular/compiler/src/compiler_util/expression_converter';
#Injectable({
providedIn: 'root'
})
export class UserServiceService {
// tslint:disable-next-line:variable-name
constructor(private _http: HttpClient) { }
public SaveUser(api: string , userData: User): Observable<any> {
// tslint:disable-next-line:no-trailing-whitespace
return this._http.post<any>(api, userData, {
headers : new HttpHeaders({
'Content-Type' : 'application/json'
})
});
}
public DeleteUser(api: string , id: number): Observable<any> {
return this._http.get<any>(api , {
// headers : new HttpHeaders({
// 'Content-Type' : 'application/x-www-form-urlencoded'
// }),
params: {
id: id.toString()
}
});
}
public editUserByID(api: string, userData: User): Observable<any> {
return this._http.post<any>(api, userData , {
// headers: new HttpHeaders({
// 'Content-Type' : 'application/json'
// })
});
}
public GetUsers(api: string): Observable<User[]> {
return this._http.get<User[]>(api);
}
public GetUsersByID(api: string , ID: number): Observable<User> {
return this._http.get<User>(api, {
// headers: new HttpHeaders({
// 'Content-Type': 'application/x-www-form-urlencoded'
// }),
params: {
ID: ID.toString()
}
});
}
}
import { Component, OnInit, OnDestroy } from '#angular/core';
import {UserServiceService} from 'src/Models/Services/user-service.service';
import { User } from 'src/Models/user';
import { Subscription } from 'rxjs';
#Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit, OnDestroy {
subscriptions: Subscription [] = [];
userData: User;
users: User[];
ifinserted: boolean;
isEdited: boolean;
// tslint:disable-next-line:variable-name
constructor(private _userService: UserServiceService) { }
ngOnInit() {
this.userData = new User();
this.ifinserted = false;
this.isEdited = false;
}
saveUser(data: User) {
console.log(data);
this._userService.SaveUser('http://localhost:58649/api/Users/PostUser' , data)
.subscribe();
this.ifinserted = true;
alert('Inserted');
}
getUser() {
this._userService.GetUsers('http://localhost:58649/api/Users/GetUsers')
.subscribe((data: User[]) => {
this.users = data;
});
}
editUser(i: number) {
this.subscriptions.push(
this._userService.GetUsersByID('http://localhost:58649/api/Users/GetUser' , i)
.subscribe((data: User) => {
this.userData = data;
this.isEdited = true;
}));
}
editUserByID(obj: User) {
this._userService.editUserByID('http://localhost:58649/api/Users/PutUser' , obj)
.subscribe();
this.isEdited = false;
alert('Edited');
}
deleteUser(i: number) {
console.log(i);
this._userService.DeleteUser('http://localhost:58649/api/Users/DeleteUser' , i)
.subscribe();
alert('Deleted');
}
ngOnDestroy() {
this.subscriptions.forEach(s => s.unsubscribe());
}
}
Related
In ASP.NET Core-6 Web API, I am implementing Fluent Validation. I have this code.
Model:
public class OAuthLoginRequest
{
public string username { get; set; }
public string password { get; set; }
}
public class OAuthLoginResponse
{
public string response_code { get; set; }
public string response_description { get; set; }
public Data data { get; set; }
public int size { get; set; }
public string access_token { get; set; }
public string refresh_token { get; set; }
public string expires_in { get; set; }
public string token_type { get; set; }
}
Validation:
public class OAuthLoginRequestValidator : AbstractValidator<OAuthLoginRequest>
{
public OAuthLoginRequestValidator()
{
RuleFor(user => user.username)
.NotNull()
.NotEmpty().WithMessage("Username field is required.");
RuleFor(user => user.password)
.NotNull()
.NotEmpty().WithMessage("Password field is required.");
}
}
AuthService:
public async Task<OAuthLoginResponse> Login(OAuthLoginRequest payload)
{
var response = new OAuthLoginResponse();
using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
try
{
var authEndpoint = _config.GetSection("Endpoints").GetValue<string>("authEndpoint");
string url = baseUrl + authEndpoint;
var request = new OAuthLoginRequest
{
username = payload.username,
password = payload.password
};
var header = new Dictionary<string, string> { };
var httpResponse = await _httpHelper.PostOrPutRequest(uri: url, methodType: HttpMethod.Post, model: request, headers: header);
if (httpResponse != null)
{
if (httpResponse.StatusCode == HttpStatusCode.OK)
{
var content = await httpResponse.Content.ReadAsStringAsync();
response = JsonConvert.DeserializeObject<OAuthLoginResponse>(content);
}
}
transaction.Complete();
}
catch (Exception ex)
{
_logger.Error("An Error occured " + ex.ToString());
response = null;
}
return response;
}
}
Controller:
[HttpPost]
[Route(ApiRoutes.Login)]
public async Task<ActionResult<OAuthLoginResponse>> Login([FromBody] OAuthLoginRequest request)
{
var result = await _myService.Login(request);
return Ok(result);
}
Dependency Injection:
public static class DIServiceExtension
{
public static void AddDependencyInjection(this IServiceCollection services)
{
// Validator
services.AddTransient<IValidator<OAuthLoginRequest>, OAuthLoginRequestValidator>();
}
}
Program.cs:
builder.Services.AddControllers()
.AddFluentValidation(options =>
{
// Automatic Validation
options.AutomaticValidationEnabled = false;
// Automatic registration of validators in assembly
options.RegisterValidatorsFromAssembly(Assembly.GetExecutingAssembly());
});
// Register Dependency Injection Service Extension
builder.Services.AddDependencyInjection();
var app = builder.Build();
I registered it in DIServiceExtension and then in Program.cs.
I deliberately post the Login without username and password, but the application did not display any validation message.
This is what I got in Postman:
Response body
{
"response_code": null,
"response_description": null,
"data": null,
"size": 0,
"access_token": null,
"refresh_token": null,
"expires_in": null,
"token_type": null
}
I expected it to display the validation message.
How can I resolve this?
From this GitHub comment,
options.AutomaticValidationEnabled = false;
is used to disable the automatic validation feature.
Approach 1: Automatic validation
Remove options.AutomaticValidationEnabled = false; from registering FluentValidation services.
Enable automatic validation with builder.Services.AddFluentValidationAutoValidation();.
using FluentValidation.AspNetCore;
builder.Services.AddControllers()
.AddFluentValidation(options =>
{
// Automatic registration of validators in assembly
options.RegisterValidatorsFromAssembly(Assembly.GetExecutingAssembly());
});
builder.Services.AddFluentValidationAutoValidation();
Reference: FluentValidation/FluentValidation.AspNetCore (Automatic Validation section)
Approach 2: Manual validation
In the Controller, get the injected IValidator<OAuthLoginRequest> service.
In the Login action, manually perform validation via await _validator.ValidateAsync(request);.
If fail validation, add the error(s) from the ValidationResult into ModelState and return the response with BadRequest.
public class AuthController : Controller
{
private readonly IValidator<OAuthLoginRequest> _validator;
public AuthController(IValidator<OAuthLoginRequest> validator)
{
_validator = validator;
}
[HttpPost]
[Route(ApiRoutes.Login)]
public async Task<ActionResult<OAuthLoginResponse>> Login([FromBody] OAuthLoginRequest request)
{
ValidationResult validationResult = await _validator.ValidateAsync(request);
if (!validationResult.IsValid)
{
// Add error into ModelState
validationResult.AddToModelState(ModelState);
return BadRequest(ModelState);
}
var result = await _myService.Login(request);
return Ok(result);
}
}
public static class FluentValidationExtensions
{
public static void AddToModelState(this ValidationResult result, ModelStateDictionary modelState)
{
foreach (var error in result.Errors)
{
modelState.AddModelError(error.PropertyName, error.ErrorMessage);
}
}
}
Reference: FluentValidation documentation (Manual Validation section)
Question:
Originally command is returning ExecutionResult, which contains Data property of type DomainOperationResult.
Only in one case I need to return some other data, which is defined as CreateOrderCommandResult which is descendant of DomainOperationResult, it contains additional field - Url.
Calling command with swagger, in the debugger, everything is shoing fine, visible id and url with Quick View.
Json(result);
it shows that it is returning Id and Url properties.
but in swagger, curl, postman, etc. only id is returned, tried everything.
there is no Url in response.
controller is working fine, no middlewares, that may change returned response.
Controller method:
{
public async Task<IActionResult> Create([FromBody] CreateOrderCommand command)
{
if (!ModelState.IsValid)
{
return await Task.FromResult(BadRequest(ModelState));
}
var result = await _commandExecutor.ExecuteAsync(command);
if (result.Success)
{
return Json(result);
}
return Json(result);
}
}
CreateOrderCommand:
{
public override async Task<CommandExecutionResult> ExecuteAsync()
{
// .....
return await OkAsync(new CreateOrderCommandResult(orderId, payment.RedirectUrl));
}
}
DomainOperationResult:
{
public class DomainOperationResult
{
public DomainOperationResult()
{
}
public DomainOperationResult(long id)
{
Id = id;
}
public long Id { get; }
}
CreateOrderCommandResult:
{
public class CreateOrderCommandResult : DomainOperationResult
{
public CreateOrderCommandResult()
: base() { }
public CreateOrderCommandResult(long id, string url)
: base(id)
{
Url = url;
}
public string Url { get; set; }
}
}
Execution result:
public class ExecutionResult
{
public ExecutionResult()
{
}
public DomainOperationResult Data { get; set; }
}
returned response:
{
"success": true,
"data": {
"id": 0
},
"error": {
"errors": null
}
}
Still no idea, why this does not works.
After some digging, found workaround.
Response.Headers.Add("Content-type", "application/json"); return Content(JsonConvert.SerializeObject(result, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }));
returning content like this works ok - at least it generates everything I need.
i have a model
public partial class TalentVendorShots
{
public int Id { get; set; }
public string Email { get; set; }
public string One { get; set; }
public string Two { get; set; }
public string Three { get; set; }
public string Four { get; set; }
public string Five { get; set; }
public string Six { get; set; }
public string Seven { get; set; }
public string Eight { get; set; }
public string Nine { get; set; }
public string Ten { get; set; }
}
and basic controllers
[Route("api/[controller]")]
[ApiController]
public class TalentVendorShotsController : ControllerBase
{
private readonly champagneDatabase _context;
public TalentVendorShotsController(champagneDatabase context)
{
_context = context;
}
// GET: api/TalentVendorShots
[HttpGet]
public async Task<ActionResult<IEnumerable<TalentVendorShots>>> GetTalentVendorShots()
{
return await _context.TalentVendorShots.ToListAsync();
}
// GET: api/TalentVendorShots/5
[HttpGet("{id}")]
public async Task<ActionResult<TalentVendorShots>> GetTalentVendorShots(int id)
{
var talentVendorShots = await _context.TalentVendorShots.FindAsync(id);
if (talentVendorShots == null)
{
return NotFound();
}
return talentVendorShots;
}
// PUT: api/TalentVendorShots/5
[HttpPut("{id}")]
public async Task<IActionResult> PutTalentVendorShots(int id, TalentVendorShots talentVendorShots)
{
if (id != talentVendorShots.Id)
{
return BadRequest();
}
_context.Entry(talentVendorShots).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!TalentVendorShotsExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
// POST: api/TalentVendorShots
[HttpPost]
public async Task<ActionResult<TalentVendorShots>> PostTalentVendorShots(TalentVendorShots talentVendorShots)
{
_context.TalentVendorShots.Add(talentVendorShots);
await _context.SaveChangesAsync();
return CreatedAtAction("GetTalentVendorShots", new { id = talentVendorShots.Id }, talentVendorShots);
}
// DELETE: api/TalentVendorShots/5
[HttpDelete("{id}")]
public async Task<ActionResult<TalentVendorShots>> DeleteTalentVendorShots(int id)
{
var talentVendorShots = await _context.TalentVendorShots.FindAsync(id);
if (talentVendorShots == null)
{
return NotFound();
}
_context.TalentVendorShots.Remove(talentVendorShots);
await _context.SaveChangesAsync();
return talentVendorShots;
}
private bool TalentVendorShotsExists(int id)
{
return _context.TalentVendorShots.Any(e => e.Id == id);
}
}
}
all of this works fine. i get information from the database fine. now i want to make a post to the table via uri. no body.for example
/api/TalentVendorShots/id=1,email=testemail should create a new record with id of 1 and email of testemail. how can i accomplish this?
The basic rule is, You should use POST if the action is not idempotent. Though you can pass the query parameters and no body to POST. But It would not make sense in this scenario. Basically query parameters are used to get/filter information.
Similar way many Web API testing tools like ARC, Swagger, and PostMan (chrome extension does not allow, but standalone application allows) does not allow to send body with the GET request. Though you can send the body in GET requests.
While calling an apiController method from Postman I encountered a problem.
the method with params mentioned in Postman client call below method
[AllowAnonymous]
[HttpPost]
public IActionResult Register([FromBody]UserDto userDto)
{
// map dto to entity
//var user = _mapper.Map<User>(userDto);
return Ok(new
{
userDto
});
//try
//{
// // save
// _userService.Create(user, userDto.Password);
// return Ok();
//}
//catch (AppException ex)
//{
// // return error message if there was an exception
// return BadRequest(new { message = ex.Message });
//}
}
which maps the UserDto..
public class UserDto
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
but instead I get the error below :
Use raw option and select json from dropdown
and add your dto value in the body.
Raw
{
"FirstName" : "yourname",
"LastName": "lastname"
}
I am using ASP CORE 2.1 and EF CORE to create Web API with 2 data table with 1 ForeignKey
Model:
public partial class AuditInfo
{
public int Id { get; set; }
public string Level { get; set; }
public string Period { get; set; }
public string Auditor { get; set; }
public virtual ICollection<Item> Items { get; set; }
}
public partial class Item
{
public int Id { get; set; }
public string Ponumber { get; set; }
public bool IsComplete { get; set; }
public AuditInfo AuditInfo { get; set; }
}
public partial class VEDHOMEContext : DbContext
{
public VEDHOMEContext()
{
}
public VEDHOMEContext(DbContextOptions<VEDHOMEContext> options)
: base(options)
{
}
public virtual DbSet<AuditInfo> AuditInfo { get; set; }
public virtual DbSet<Item> Item { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.HasAnnotation("ProductVersion", "2.1.1-rtm-30846")
.HasAnnotation("Relational:MaxIdentifierLength", 128)
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("auditAPI.Models.AuditInfo", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<string>("Auditor");
b.Property<string>("Level");
b.Property<string>("Period");
b.HasKey("Id");
b.ToTable("AuditInfo");
});
modelBuilder.Entity("auditAPI.Models.Item", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
b.Property<int?>("AuditInfoId");
b.Property<bool>("IsComplete");
b.Property<string>("Ponumber");
b.HasKey("Id");
b.HasIndex("AuditInfoId");
b.ToTable("Item");
});
modelBuilder.Entity("auditAPI.Models.Item", b =>
{
b.HasOne("auditAPI.Models.AuditInfo", "AuditInfo")
.WithMany("Items")
.HasForeignKey("AuditInfoId");
});
}
}
Controller:
[Route("api/[controller]")]
[ApiController]
public class AuditInfoesController : ControllerBase
{
private readonly VEDHOMEContext _context;
public AuditInfoesController(VEDHOMEContext context)
{
_context = context;
}
// GET: api/AuditInfoes
[HttpGet]
public IEnumerable<AuditInfo> GetAuditInfo()
{
return _context.AuditInfo;
}
// GET: api/AuditInfoes/5
[HttpGet("{id}")]
public async Task<IActionResult> GetAuditInfo([FromRoute] int id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var auditInfo = await _context.AuditInfo.FindAsync(id);
if (auditInfo == null)
{
return NotFound();
}
return Ok(auditInfo);
}
// PUT: api/AuditInfoes/5
[HttpPut("{id}")]
public async Task<IActionResult> PutAuditInfo([FromRoute] int id, [FromBody] AuditInfo auditInfo)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != auditInfo.Id)
{
return BadRequest();
}
_context.Entry(auditInfo).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!AuditInfoExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
// POST: api/AuditInfoes
[HttpPost]
public async Task<IActionResult> PostAuditInfo([FromBody] AuditInfo auditInfo)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
_context.AuditInfo.Add(auditInfo);
await _context.SaveChangesAsync();
return CreatedAtAction("GetAuditInfo", new { id = auditInfo.Id }, auditInfo);
}
// DELETE: api/AuditInfoes/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteAuditInfo([FromRoute] int id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var auditInfo = await _context.AuditInfo.FindAsync(id);
if (auditInfo == null)
{
return NotFound();
}
_context.AuditInfo.Remove(auditInfo);
await _context.SaveChangesAsync();
return Ok(auditInfo);
}
private bool AuditInfoExists(int id)
{
return _context.AuditInfo.Any(e => e.Id == id);
}
}
However i got return null for the item related data, how can i fix it?
i am new to this framework, any help would appreciate, thanks.
[{"id":1,"level":"level1","period":"jan","auditor":"A","items":null},{"id":2,"level":"level2","period":"feb","auditor":"B","items":null}]
expected output:
[{"id":1,"level":"level1","period":"jan","auditor":"A","items":{"Id":1,"Ponumber":"0001","IsComplete":"True","AuditInfoId":1},{"id":2,"Ponumber":"0002","IsComplete":"True","AuditInfoId":1}}]
To who have similar problem, I solve it by adding
services.AddMvc()
.AddJsonOptions(options => {
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
and edit controller
public async Task<List<AuditInfo>> GetAuditInfo()
{
//return _context.AuditInfo;
var infoes = await _context.AuditInfo.Include(a => a.Items).ToListAsync();
return infoes;
}
I'm not sure if you've seen the accepted answer to this question, but the problem is to do with how the JSON Serializer deals with circular references. Full details and links to more references can be found at the above link, and I'd suggest digging into those, but in short, adding the following to startup.cs will configure the serializer to ignore circular references:
services.AddMvc()
.AddJsonOptions(options => {
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});