I changed my Apartments Model Class by adding a BuyerID which is a foreign key to another Buyer Class like this:
public class Apartment
{
[Key]
public int ID { get; set; }
public string Title { get; set; }
public int NbofRooms { get; set; }
public int Price { get; set; }
public string Address { get; set; }
public int BuyerId { get; set; }
}
Also I have my Buyers Model Class as the following:
public class Buyer
{
[Key]
public int ID { get; set; }
public string FullName { get; set; }
public int Credit { get; set; }
public ICollection<Apartment> apartments { get; set; }
}
So it also contains a collection of Apartments.
and because of this maybe my Get method isn't working anymore and is returning the following error: GET http://localhost:54632/api/Apartments net::ERR_CONNECTION_RESET 200 (OK)
The only GET Method not working is this one:
// GET: api/Apartments
[HttpGet]
public IEnumerable<Apartment> GetApartments()
{
return _context.Apartments;
}
Otherwise the others such as this:
// GET: api/Apartments/5
[HttpGet("{id}")]
public async Task<IActionResult> GetApartment([FromRoute] int id)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var apartment = await _context.Apartments.SingleOrDefaultAsync(m => m.ID == id);
if (apartment == null)
{
return NotFound();
}
return Ok(apartment);
}
is working fine.Also if I try the link on chrome it returns the apartments but if I try it on Postman or Angular App it returns the error. What could be the cause of this error?
Thank you.
I had the same problem, and it was due to having created a self-referencing loop in the data I was trying to serialize. Looking at the recent change you had made it looks like you also created an object tree with a self referencing loop by referencing back to a Buyer from Apartments.
Json.Net gets upset by this and gives up. I would expect an exception to be thrown as in this question, but I didn't get one, I had the same symptoms as you describe.
If you are having the same root problem, it is solved by setting JSON.Net to detect and ignore self referencing loops during startup configuration as explained here or here for asp.net core.
Asp.Net:
HttpConfiguration config = GlobalConfiguration.Configuration;
config.Formatters.JsonFormatter
.SerializerSettings
.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
Asp.net Core:
services.AddMvc().AddJsonOptions(options =>
{
options.SerializerSettings.ReferenceLoopHandling =
Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
open chrome then open DevTools by pressing F12 and navigate to network tab. Find your API request and select copy > copy as cURL
now you can compare curl request and postman request in order to see difference. The difference will give you the problem.
Related
I have encountered really weird situation. I am developing a net 5 api, and (among ohther entities) have three tables, Doctor, Specialization, and DoctorSpecialization. My entities:
public class Doctor
{
public int Id { get; set; }
public string Name { get; set; }
public string Resume { get; set; }
public ICollection<DoctorSpecialization1> DoctorSpecializations { get; set; }
}
public class DoctorSpecialization
{
public int Id { get; set; }
public int Doctor1Id { get; set; }
[ForeignKey("Doctor1Id")]
public Doctor1 Doctor { get; set; }
public int Specialization1Id { get; set; }
[ForeignKey("Specialization1Id")]
public Specialization1 Specialization { get; set; }
}
public class Specialization
{
public int Id { get; set; }
public string SpecializationName { get; set; }
}
I want to fetch all the specializations associated with the certain doctor, therefore I created a service:
public class DoctorService : IDoctorService
{
public async Task<List<Specialization>> GetAllSpecializationsForDoctor(int id)
{
var doctor = await _context.Doctors.Where(x => x.Id == id).FirstOrDefaultAsync();
var doctorSpecializations = await _context.DoctorSpecializations.
Where(x => x.DoctorId == doctor.Id)
.ToListAsync();
IEnumerable<int> ids = doctorSpecializations.Select(x => x.SpecializationId);
var specializations = await _context.Specializations.Where(x =>
ids.Contains(x.Id)).ToListAsync();
return specializations;
}
}
In the end, I am adding a method in my controller which is supposed to fetch specializations based on doctor's id:
[HttpGet("specializations/{id}")]
public async Task<ActionResult<List<Specialization1>>> GetSpecializationsForDoctor(int id)
{
var doctor = await _doctorService.FindDoctorById(id);
if (doctor == null) return NotFound();
var specialization = _doctorService.GetAllSpecializationsForDoctor(id);
return Ok(specialization);
}
When I run this in postman, I get the error stated in the title of this question. However, I encountered an article that explains I should install newtonsoft.json and make some changes in my Startup in order to overcome this issue. So therefore I installed Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.10" and made changes in my Starup as follows:
services.AddControllers().AddNewtonsoftJson(options =>
options.SerializerSettings.ReferenceLoopHandling =
Newtonsoft.Json.ReferenceLoopHandling.Ignore);
This time I get the expected result, but my postman shows tons of data before giving me the wanted result, and I wonder is it ok to return this much data to the client. Can somebody explain me what is going on, tnx in advance!
Apparently the solution was so simple, I missed the await in:
var specialization = await
_doctorService.GetAllSpecializationsForDoctor(id);
Once again I managed to find solution thanks to stackoverflow, because apparently someone else had this problem in: JsonException: A possible object cycle was detected which is not supported. This can either be due to a cycle or if the object depth is larger than
So please everyone, don't be so superficial as I was, make sure to use await and save your time. Thanks again to the community:).
I'm learning Blazor, and creating a website with a simple image viewer.
I have the following classes describing an Image and any Tags that are related:
public class GalleryImage
{
public int ID { get; set; }
public string FileName { get; set; }
public virtual ICollection<GalleryImageTag> ImageTags { get; set; }
}
public class GalleryImageTag
{
public int ID { get; set; }
public string Tag { get; set; }
public virtual ICollection<GalleryImage> GalleryImages { get; set; }
}
As you can see they describe a many-to-many relationship.
In my Controller I have:
[HttpGet("GetGallery")]
public async Task<IActionResult> GetGallery()
{
List<GalleryImage> galleryImagesDB = await _context.GalleryImages
//.Include(a => a.ImageTags)
.ToListAsync();
return Ok(galleryImagesDB);
}
My Blazor page has:
private List<GalleryImage> galleryImages = new();
protected override async Task OnInitializedAsync()
{
try
{
galleryImages = await Http.GetFromJsonAsync<List<GalleryImage>>("api/Gallery/GetGallery");
}
catch (Exception ex)
{
Console.WriteLine($"Error in Gallery.OnInitializedAsync : {ex.Message}");
}
}
This works fine to retrieve a List of GalleryImages from the database. However, when I uncomment the line
.Include(a => a.ImageTags)
then it fails. If I break at the return then galleryImages correctly contains a List of GalleryImages, and any that have been Tagged include a List of GalleryImageTags. But I get an error in the Chrome console:
Error in Gallery.OnInitializedAsync : Response status code does not indicate success: 500 (Internal Server Error).
What am I doing wrong?
Client and Server are both using .Net 5.0.
You have a circular reference. This will return from the DB but will cause the serialisation error. You can put [JsonIgnore] attribute on one of the collections to prevent to circular serialisation.
I am currently developing a web api in .NET Core 3. I currently have the following model for my error response object:
public class ErrorRo
{
public string Message { get; set; }
public int StatusCode { get; set; }
public string Endpoint { get; set; }
public string Parameters { get; set; }
public string IpAddress { get; set; }
}
This is a mandated response I need to implement, management has pushed this. It allows more verbose error messages for people hitting our API so that they know what went wrong.
At the moment I am currently populating this object manually in the methods themselves. Is there a way where I can overwrite the response methods. I.e. can I override the BadRequest of IActionResult to automatically populate these fields?
Thanks!
You can use result filters for this purpose. Add a filter which repalces result before sending it back
Model
public class CustomErroModel
{
public string Message { get; set; }
public int StatusCode { get; set; }
public string Endpoint { get; set; }
public string Parameters { get; set; }
public string IpAddress { get; set; }
}
Filter
public class BadRequestCustomErrorFilterAttribute : ResultFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext context)
{
//todo: check for BadRequestObjectResult if anything is returned for bad request
if (context.Result is BadRequestResult)
{
var result = new CustomErroModel
{
StatusCode = 200, //you status code
Endpoint = context.HttpContext.Request.GetDisplayUrl(),
Message = "some message",
IpAddress = context.HttpContext.Connection.RemoteIpAddress.ToString(), //find better implementation in case of proxy
//this returns only parameters that controller expects but not those are not defined in model
Parameters = string.Join(", ", context.ModelState.Select(v => $"{v.Key}={v.Value.AttemptedValue}"))
};
context.Result = new OkObjectResult(result); // or any other ObjectResult
}
}
}
Then apply filter per action or globally
[BadRequestCustomErrorFilter]
public IActionResult SomeAction(SomeModel model)
or
services
.AddMvc(options =>
{
options.Filters.Add<BadRequestCustomErrorFilterAttribute>();
//...
}
Well it depends on the scenario, but one possible approach could be to use a middleware using a similar strategy like the one described in this question, so that you complete the response with extra information.
This is a C# Question, using .NET framework built on Asp.NET Boilerplate.
Again, to re-emphasis the question being asked is "HOW...", so if an answer that was provided was a url link or a descriptive explanation on how something was supposed to be done, i would very much appreciate it. (Dont answer questions on how to tie shoelace by showing a picture of a tied shoe, nor do you answer "how to fish" by showing a recording of someone fishing...)
Since the question is pretty basic (i don't need to rephrase/repeat the header again), i'll give an example.
If i have a Forum service, and i create a class to load a Thread. Inside that thread class should be some sort of collection, array, list, or even a dbset of Post that is pulled on construct.
[Table("Thread", Schema = "dbo")]
public class ThreadModel
{
[Key]
public long Id { get; set; }
public string Title { get; set; }
//Idea 1
//Value should automatically be pulled and cached the moment class connects to database
public Post[] Posts { get; set; }
//Idea 2
//Post has a constructor to return all post that matches a thread id. While new tag keeps the return value constantly refreshed.
public Post[] Posts { get { return new Post(this.Id) } }
//Idea 3
//Not sure how collection is supposed to work. Does it automatically just pull or will i need to make a method to request?
public virtual ICollection<Post> Posts { get; set; }
//Example constructor
//When connected to database key-value pairs that match database labels will automatically get stored in class
protected ThreadModel()
{
//Idea 1-A
//Should be a value of null or empty if database yields no results
Posts = new Post();
}
public ThreadModel(int threadid) : this()
{
//Idea 1-A
Id = threadid;
//new Post => returns all posts in db
//Posts default value is all post in db
Posts = Posts.Select(post => post.threadid == this.id)
//Idea 3-A
Posts = Posts.Get(post => post.threadid == this.id)
//Idea 4
Posts = new Posts().GetThread(threadid);
}
}
Side questions
If all entities are created by inheriting Entity then at what point am i exposed to EntityFramework and DbContext?
I love this example here, submitted by a user as they attempt to connect ABP to their database. But their example doesn't show parent/child resources. I'm unable to find the guide they used to create that, and how it relates back to using ABP to fetch EntityFramework's DbContext example
How does this work? I'm unable to find instructions or explanation for this? (What am i to enter into google to get answers on these mechanics?)
[Table("AbpItems")]
public class Item : Entity
{
[ForeignKey("PostId")]
public Post Post { get; set; }
public int PostId { get; set; }
}
How does this integrate into/with abp's EntityFramework?
Where am i supposed to be creating my Database Table/Class? The project follows the Core.csproj, Application.csproj, and EntityFramework.csproj assembly layout. But it seems like every example is creating the classes at different stages or locations of the solution.
use GetAllIncluding. See https://github.com/aspnetboilerplate/aspnetboilerplate/issues/2617
Here's a complete solution ;
namespace EbicogluSoftware.Forum.Threads
{
[Table("Threads")]
public class Thread : FullAuditedEntity
{
[Required]
[StringLength(500)]
public virtual string Title { get; set; }
[Required]
[StringLength(2000)]
public virtual string Text { get; set; }
public virtual List<Post> Posts { get; set; }
public Thread()
{
Posts = new List<Post>();
}
}
[Table("Posts")]
public class Post : FullAuditedEntity
{
[Required]
[StringLength(2000)]
public virtual string Text { get; set; }
}
public class ThreadDto
{
public string Title { get; set; }
public string Text { get; set; }
public List<PostDto> Posts { get; set; }
public ThreadDto()
{
Posts = new List<PostDto>();
}
}
public class PostDto
{
public string Text { get; set; }
}
public class ThreadAppService : IApplicationService
{
private readonly IRepository<Thread> _threadRepository;
public ThreadAppService(IRepository<Thread> threadRepository)
{
_threadRepository = threadRepository;
}
public async Task<List<TenantListDto>> GetThreads()
{
var threads = await _threadRepository.GetAllIncluding(x => x.Posts).ToListAsync();
return threads.MapTo<List<TenantListDto>>();
}
}
}
Where am i supposed to be creating my Database Table/Class?
You can create them in YourProject.Core.proj
I'm listening to "push" notifications coming into my server. I've set up SubscriptionModel with all possible properties, and I can correctly iterate through the JSON body coming through, parse each Subscription, and modify the output before returning the list I created. However, I'd like to know how I might go about removing properties of SubscriptionModel when I don't need to return them at all; or removing them if they're null before responding back with List<SubscriptionModel> subscriptions.
namespace TextMessagingListener.Controllers
{
public class SubscriptionModel
{
public long push_id { get; set; }
public string request_id { get; set; }
public string subscription_id { get; set; }
public string message { get; set; }
public string status_code { get; set; }
public string error_message { get; set; }
}
[Route("api/[controller]")]
public class SubscriptionController : Controller
{
// PUT api/subscription
[HttpPut]
public List<SubscriptionModel> Put([FromBody] List<SubscriptionModel> model)
{
// Receive a report of whether your subscription(s) was successfully added or not.
List<SubscriptionModel> subscriptions = new List<SubscriptionModel>();
foreach (SubscriptionModel m in model)
{
m.message = "Push notification successfully received.";
subscriptions.Add(m);
}
return subscriptions;
}
}
}
The only solution I can think of is to create another object which will just be for returning information; and applying each subscriptions item I want to send on to that.
You can't. You'd need another class. A "light" version that contains just the properties. Or you could do an anonymous type, but that is difficult to work with. I agree with the other guy on your naming conventions though :).