How does breeze detemine API action method based on entity name? - dictionary

I have a simple entity: Contact
DBContext line:
public DbSet<Contact> Contacts { get; set; }
API Controller:
[HttpGet]
public IQueryable<Contact> Contacts()
{
return _contextProvider.Context.Contacts;
}
In my data retrieval in breeze client I do this:
var query = EntityQuery.from("Contacts")
.orderBy(orderBy.obContact)
That works great, and I can understand that the from parameter "Contacts" must match the API action method.
In my getByID I do this:
return manager.fetchEntityByKey("Contact", contactId, true)
That's working great, and it also makes a call to the "Contacts" API method. But I would like to know how breeze took the parameter "Contact" and knew to call the "Contacts" method.
Is this in the metadata?
Did it come from my DBSet line in my dbcontext? (I'm thinking it did, but would like confirmation). If that's the case then these two names must be equal right?
[HttpGet]
public IQueryable<Contact>Contacts() // The HTTP action method name
public DbSet<Contact> Contacts { get; set; } // The DbSet variable
I tried these changes:
public DbSet<Contact> DBSetContacts { get; set; }
and
[HttpGet]
public IQueryable<Contact> Contacts()
{
return _contextProvider.Context.DBSetContacts;
}
My first query above that returns an array ran fine.
My fetch by ID failed, it was trying to find URI resource "DBSetContacts".
My conclusion is that the DbSet variable has to have the same name as the URI method for the fetchByID to work. Is that correct?

Breeze internally keeps an EntityType/ResourceName map. ResourceNames are the names of the server side methods.
The EntityType/ResourceName map is one of the items in the Breeze MetadataStore. The map of a new MetadataStore starts empty. Breeze populates it from server metadata if those metadata contain EntityType/Resource mappings.
As you guessed, the Breeze EFContextProvider generates metadata with mappings derived from Entity Framework DbSet names. When you define a Person class and exposed it from a DbContext as a DbSet named "Persons", the EFContextProvider metadata generator adds a mapping from the "Persons" resource name to the Person entity type.
For more information see the 'EntityType/ResourceName" mapping subtopic on this page.
http://www.getbreezenow.com/documentation/querying-locally
You can also update the EntityType/ResourceMap explicitly via the method below:
http://www.getbreezenow.com/sites/all/apidocs/classes/MetadataStore.html#method_setEntityTypeForResourceName

Related

How to create a basic web api to get data

Trying to create a basic web api for my database table where anyone can view my table data using a URL (JSON format?). My understanding is that I should be able to get my data by typing in table name in URL.
my database table name is myTable which is mapped to model class My_Model
Issue: There are no errors but when i try to type in url https://localhost:7048/myTable/ it return page not found
[Route("[controller]")]
[ApiController]
public class My_Controller : Controller
{
public My_Services _services { get; }
public My_Controller(My_Services services)
{
this._services = services;
}
// Database Table Name = "myTable"
[HttpGet]
public IQueryable<My_Model> Get()
{
return (IQueryable<My_Model>)_services.Get_All_Data();
}
public IActionResult Index()
{
return View();
}
}
My_Services class - where get all data from table
public async Task<IQueryable<My_Model>> Get_All_Data()
{
IQueryable<My_Model> Query = from x in _context.My_DbSet
select x;
return Query;
}
My understanding is that I should be able to get my data by typing in
table name in URL.
No, this is not how it works. You should check Routing to controller actions in ASP.NET Core. In your example you should be able to access your data using this url: https://localhost:7048/My_. The reason is that your controller has the attribute [Route("[controller]")]. [controller] is a special value which means that the route should be the controller class name without the Controller suffix so My_ in this case.
If you want to have access using this url: https://localhost:7048/myTable then you need to either change the attribute to this: [Route("myTable")] or to change the controller class name to MyTableController.
Also your Get method looks wrong. You should await the _services.Get_All_Data method instead of casting to IQueryable<My_Model>:
[HttpGet]
public async Task<IQueryable<My_Model>> Get()
{
return await _services.Get_All_Data();
}

Including Identity User with Entity Framework doesn't work

I am having trouble including my Identity User in query results. Other entities are included just fine, no matter how many levels deep.
Here's the model I'm using.
Building * --- 1 City
* *
| /
| /
1 1
ApplicationUser
And the context:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<City> Cities { get; set; }
public DbSet<Building> Buildings { get; set; }
}
Both Building and City have these properties:
public Guid ApplicationUserId { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
The query I'm using to retrieve data:
var building = context.Buildings
.Include(c => c.ApplicationUser)
.Include(c => c.City)
.Include(c => c.City.ApplicationUser)
.First();
In the result City is populated just fine, however ApplicationUser is not.
Could this be a naming issue? I've already tried UserId / User and AspNetUserId / AspNetUser as property names without succes.
I'm using Migrations to create the database. The table name that gets created for users is AspNetUsers.
I'm using entity framework 7 beta 7, not sure if this applies to other versions as well.
These are the files generated by EF Migrations.
ApplicationDbContextModelSnapshot.cs
20150929181902_Init.cs
20150929181902_Init.Designer.cs
(I noticed I forgot to include the Building > City relation when generating files for upload, but that shouldn't matter for the example)
I've finally figured it out.
ApplicationUser inherits from IdentityUser which inherits from IdentityUser<string>. The generic type is used as the primary key, so a string!
I changed my Guid foreign key properties to strings and now everything is working.
Just to help anyone who also have a similar issue. I was facing same thing, same scenario: My custom identity user has some related entities and using .Include was not working. None of them would come back. But they used to.
Turns out I had created a custom ApplicationUserStore to automatically include the entities I would normally always need when retrieving a User but I had only overridden FindByIdAsync method. When I tried to use FindByNameAsync no entity would come back, obviously. Just had to override this and the other Find methods.

ASP.Net Model without DbContext?

I am new to ASP.Net, if my question sounds very basic, please be polite.
I have created a ASP.Net MVC4 project. A page in the application will display names of the files in tabular form.
The names of the files are obtained by finding files in a particular folder on the server. So there is no need for me to have a database for model.
When user opens the page, the server side code will list all the files in the directory and should return a list of Strings.
I am following ASP.Net MVC tutorial here and it appears I have to have a DBContext class and also a database. In my case that's not needed
So that question is can I add my model without having to add code like below and still be able to use the feature of model ? any simple example would be great.
public class MovieDBContext : DbContext
{
public DbSet<Movie> Movies { get; set; }
}
Any class can serve as a model in this case. For example, if you just want to have a Movie model, you can have something as simple as this:
public class Movie
{
public string Title { get; set; }
}
A view can bind to that model, to an enumeration of that model, etc.
For fetching your data from the file system, one approach could be a simple factory method on that model. Maybe something like this:
public class Movie
{
public string Title { get; set; }
public static IEnumerable<Movie> GetMovies()
{
// get the list of movies from the file system, for example as a list of strings
var movies = SomeFileSystemInteraction();
return movies.Select(m => new Movie { Title = m });
}
}
Then in your controller you can get the list of movies to bind to the view:
public ActionResult Index()
{
return View(Movie.GetMovies());
}
There's no need for a database, it's just used in tutorials because it's the most common case. But you can bind your views to any object you'd like.
You do not need that MovieDBContext class if you are not dealing with database. But having a model is a good idea to represent your entity(in this case the Folder). It is just a POCO class.
public class Folder
{
public string Name { set;get;}
public int NumberOfchilds { set;get;}
//Other properties as needed.
}
Now you can use the Model class to pass data between differnt places. For example. You can move the code which reads the data from file system to a Service class method and the method can return a list of this class/A single instance of this class as needed. Your controller action method can call the service method.
public class FolderService
{
public Folder GetRecentlyCreatedFolder()
{
var folder=new Folder();
//Set the properties of this object
// folder.Name="MySecret";
return folder;
}
}
and in your Action method
public ActionResult Items()
{
var srv=new FolderService();
var recentFolder=srv.GetRecentlyCreatedFolder();
return View(recentFolder);
}
Yes, you can use a model which is not stored in a database at all. Your case sounds like an obvious example.
Model, View, Controller makes database access easily abstractable but doesn't necessitate a database.
As much as I like entity framework I've never loved how most tutorials for MVC seem to marry the two - They are essentially unrelated and I think it really muddies the waters for a lot of programmers new to the framework.
All you need for a model is just a plain old class. Instead of using the dbcontext you'd simply use whatever code you need to load your data.

Entity Framework 4 (using EDMX), how to add a field into to model that DB does not have the field actually

I need to add a field into model that Database does not have the field actually.
Because, firstly I tried to add the field into Entity class only.
public partial class Weborder
{
(Auto Generated)
public int orderno {get; set;}
.
.
.
(Add Manually)
public string newField1 {get; set;} //this is new field that DB does not have
public string newField2 {get; set;} //this is new field that DB does not have
}
and later, when I update EDXM then EDMX remove the new fields because the database does not have the field. :(
So I add the field into EDMX model manually. (Add -> Scalar Property)
then an error occur while compiling, the error message say :
Error 1 Error 3004: Problem in mapping fragments starting at line 399:No mapping specified for properties ...
An Entity with Key (PK) will not round-trip when:...
Anybody know how to add new fields into entity class ?
Thank you!
EDITED FOR :
If your model is a representation of your database and in the database you don't have the field, why do you want to add it manually?
=>
When retrieve data, the return type of object is the entity class.
and before passing data from controller to view, I need to add more data(fields) into the IQueryable result.
ex)
public DbSet<WEBORDERLN> WEBORDERLNs { get; set; }
//repository
public IQueryable<WEBORDERLN> WebOrderLns
{
get { return context.WEBORDERLNs; }
}
and now I get the weborderln data in controller. and before passing view, I need to
add extra data into the result.
var data = webOrderLnRepository.WebOrderLns.Where(e => e.PICKNO == OrderNo).ToList();
foreach (WEBORDERLN weborderln in data)
{
weborderln.[NEW FIELD] = "EXTRA DATA"; //// FOR THIS, I NEED TO ADD NEW FILED INTO ENTITY CLASS
}
//return data
I hope it could explain the question :)
Thanks again.
You must create a new partial part of your entity class (in the new .cs file) and add new fields to that class. You must not modify the partial part created by autogeneration because autogenerated files will be overwritten every time you change EDMX file. You also must not include the field in EDMX because EDMX defines your mapping to database = it contains only fields in database.
Create a new file WebOrderPart.cs in the same assembly and namespace as your autogenerated classes containing:
public partial class Weborder
{
public string newField1 {get; set;}
public string newField2 {get; set;}
}
Dosn't [NotMapped] work.
[NotMapped]
public string newField1 {get; set;}
First of all, you shouldn't modify the data model file. This file represents your data.
Second, you shouldn't be returning your data model objects/collections from your Repository. This is a very bad practice because you are creating a dependency between the Controller/View and the Model. I suggest you create custom Model objects that contain the properties you need in your View, map your entities to those Model objects and only return Model objects or collections of Model objects from your Repository.

how to edit json data runtime?

i want to add the data to existing generated json data in my asp.net mvc application , what i have to do ?
means , suppose i have class Company that having list of Departments as property. but json serialization is not able to support such kind of circular reference. so i thought how if, i get serialize the Company object first without list of Departments, then get departments for each company and then serialize this list and append data to company serialized data. i know this may be wrong way . but i have to do because of time ultimatum. please guide.
You could define a view model where you won't have any circular references:
public class DepartmentViewModel
{
public string DepartmentName { get; set; }
}
public class CompanyViewModel
{
public IEnumerable<DepartmentViewModel> Departments { get; set; }
}
and then you would map between your model and view model (you could use AutoMapper for this) and finally return the view model to the view.
For example:
public ActionResult Index()
{
var companies = _repository.GetCompanies();
var companiesVM = Mapper.Map<IEnumerable<Company>, IEnumerable<CompanyViewModel>>(companies);
return Json(companiesVM, JsonRequestBehavior.AllowGet);
}
Now you no longer would have circular references and you will be able to successfully serialize the view model to JSON and you would only pass the information that is required to the view.

Resources