WEB API 2 Self-hosted hostname issues - binding

I'am trying to make a self-hosted web api service. I followed a tutorial and it works fine on my local computer.
localhost/api/values responds fine with the expected JSON.
Now, I have a server binded to the DNS "myserver.mycompany.com". When I start my WebApi 2 service on this server and try to call myserver.mycompany.com/api/values I have a 404 page not found error.
If I browse locally on this server and call the localhost/api/values url it works fine.
Here is the code of the Startup class :
using Owin;
using System.Web.Http;
namespace SelfHostedWebApi2
{
public class Startup
{
// This code configures Web API. The Startup class is specified as a type
// parameter in the WebApp.Start method.
public void Configuration(IAppBuilder appBuilder)
{
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseWebApi(config);
}
}
}
And here is how I start the server :
using Microsoft.Owin.Hosting;
using System;
using System.Net.Http;
namespace SelfHostedWebApi2
{
public class Program
{
static void Main()
{
string baseAddress = "http://localhost:80/";
// Start OWIN host
try
{
WebApp.Start<Startup>(new StartOptions(url: baseAddress));
HttpClient client = new HttpClient();
var response = client.GetAsync(baseAddress + "api/values").Result;
Console.WriteLine(response);
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
}
catch (Exception ee)
{
Console.WriteLine("Erreur : " + ee.ToString());
}
Console.ReadLine();
}
}
}
Thank you for your help

You should change your baseAddress so that its endpoint matches your hostname or you may use a WeakWildcard * to match all possible hostnames.
This one should work: string baseAddress = "http://*:80/";

Related

fHow to have separate login/logout screen with Azure AD authentication

I have previously integrated with Okta and they have a sign in widget you can put into a page to log in with and call a controller to initiate the authentication/claims process. However, Azure AD does not seem to have anything like this so I wanted to use my razor page with our logo on it located in /pages/login/index to be the only folder for anonymous viewing. Basically I would like it to be the first screen anyone sees when they come to the site when not logged in and it will have a button which calls a controller post action to take you to Microsofts Azure AD Login screen. I have not seen any examples of this online so I am curious if this is even possible?
My current solution takes you straight to microsofts login:
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using Project.Models;
using DocumentFormat.OpenXml.Office2016.Drawing.ChartDrawing;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.UI;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
//authentication pipeline
var initialScopes = builder.Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
builder.Services.AddControllers(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
builder.Services.AddRazorPages()
.AddMicrosoftIdentityUI();
var RootPath = builder.Environment.ContentRootPath;
var WebPath = builder.Environment.WebRootPath;
var fileDirectory = Path.Combine(Directory.GetParent(RootPath).Parent.ToString(), "armsfiles");
IFileProvider physicalProvider = new PhysicalFileProvider(fileDirectory);
builder.Services.AddSingleton<IFileProvider>(physicalProvider);
//Not needed. We are not using this level of abstraction but may move towards it one day so possibly keep.
var connectionString = builder.Configuration.GetConnectionString("DBContext");
builder.Services.AddDbContext<DBContext>(options => options.UseSqlServer(connectionString));
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
else
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
//We are making it so armsfiles are not accessible outside of arms so if we move to box or onedrive then the parameter may need to be removed.
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = physicalProvider,
RequestPath = "/files"
});
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.MapControllerRoute(
name: "default",
pattern: "{controller}/{action}/{id?}",
defaults: new { controller = "Home", action = "Index" });
app.Run();
I was thinking I could add this:
// Add services to the container.
builder.Services.AddRazorPages().AddRazorPagesOptions(options =>
{
options.Conventions.AllowAnonymousToFolder("/Login");
options.Conventions.AuthorizeFolder("/");
options.Conventions.AuthorizeFolder("/files");
});
But since there is no redirect for non logged in users that I can find I do not know if this option even makes a difference. So basically it is unclear how to setup the Program file to ensure not logged in users are redirected to this razor page (/login/index) and also what a controller for a sign in and sign out button would even look like! I am surprised I have struggled to find an example of this for ASP.NET Core 6.
**EDIT 11/22/2022
I have since got every component of my question solved except when a user goes to the site, if they are not authenticated I want to redirect them to "/login/" which hosts a page with a button that OnPost() does the following challenge:
public class IndexModel : PageModel
{
private string SignedOutRedirectUri;
public IndexModel(IConfiguration configuration)
{
SignedInRedirectUri = configuration["AzureAd:SignedInRedirectUri"];
}
public void OnGet()
{
}
public IActionResult OnPost()
{
return Challenge(
new AuthenticationProperties { RedirectUri = SignedInRedirectUri },
OpenIdConnectDefaults.AuthenticationScheme);
}
}
Is there a way to redirect users to a login page similar to how ASP.NET Core allows a redirect for their cookie options? ie,
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(cookieOptions =>
{
cookieOptions.Cookie.Name = "UserLoginCookie";
cookieOptions.LoginPath = "/Login/";
cookieOptions.ExpireTimeSpan = TimeSpan.FromMinutes(30);
cookieOptions.SlidingExpiration = true;
});
Create HomePageRouteModelConvention.
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace WebApplication3
{
public class HomePageRouteModelConvention : IPageRouteModelConvention
{
public void Apply(PageRouteModel model)
{
if (model.RelativePath == "/Pages/Index.cshtml")
{
var currentHomePage = model.Selectors.Single(s => s.AttributeRouteModel.Template == string.Empty);
model.Selectors.Remove(currentHomePage);
}
if (model.RelativePath == "/Pages/Login/Index.cshtml")
{
model.Selectors.Add(new SelectorModel()
{
AttributeRouteModel = new AttributeRouteModel
{
Template = string.Empty
}
});
}
}
}
}
Refer my startup.cs file.
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.UI;
namespace WebApplication3
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddAuthorization(options =>
{
// By default, all incoming requests will be authorized according to the default policy.
options.FallbackPolicy = options.DefaultPolicy;
});
builder.Services.AddRazorPages()
.AddMicrosoftIdentityUI().AddRazorPagesOptions(options =>
{
options.Conventions.Add(new HomePageRouteModelConvention());
options.Conventions.AllowAnonymousToFolder("/Login");
options.Conventions.AuthorizeFolder("/");
options.Conventions.AuthorizeFolder("/files");
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.MapControllers();
app.Run();
}
}
}
Others
Test Result:

Resource translations no longer applied x time after installation

I've been tasked with making an update to an existing asp core mvc site. I had to add a filter to an existing report.
The site uses resource files for string translations.
After uploading the site to the server, the site is running, everything is fine. the site runs under a different port for test purposes than the live site.
The moment my colleague tests the site, the site shows with it's keys only.
When i check immediatly after, for me as well, no resource strings are shown, only the keys.
Restarting IIS doesn't help. The only thing that temporarily works, is copying the files again from my computer to the server. Then the translation strings work again. Untill they don't.
I have no clue as what could be the cause and i am looking for ideas to check.
The current things i want to confirm is, when it reverts to keys, if the .resources.dll is still there. Although the virus scanner logs don't show activity, and the production site which is on the same server doesn't expoerince this problem, sepite having the same .resources.dll.
If you think knowing the startup.cs might be helpfull, let me know, or if someone thinks 'if i could only know that', just give out a shout. All input is welcome. It's difficult for me now to know what info could be usefull and what not. Posting a link to the whole reporsitory isn't really an option for me. I hope you understand.
EDIT 2021/02/23
Added a redacted startup.cs
Personal progress, it's not the wrong language it's picking up rather then it's showing the resource keys after x time. The resource keys happen to be in english. It's as if the french resource dll gets deleted, but only infor the test version of the site.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
...
using DevExpress.AspNetCore;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
namespace ...
{
public class Startup
{
private const string Loginpath = "";
public static string LiveUrl { get; set; }
public IConfiguration Configuration { get; }
public IHostingEnvironment HostingEnvironment { get; }
private RequestLocalizationOptions SiteLocalizationOptions { get; }
public Startup(IConfiguration configuration, IHostingEnvironment env)
{
IList<CultureInfo> supportedCultures = new List<CultureInfo>
{
// new CultureInfo("en-US"),
new CultureInfo("fr-FR"),
};
SiteLocalizationOptions = new RequestLocalizationOptions()
{
DefaultRequestCulture = new RequestCulture("fr-FR"),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
};
//the third culture provider looks at the browsers preferenced culture. When the first visitor give english as prefered language, somehow parts of the site become english for subsequent all visitors.
//at some point there was an english site option, and artifacts of that remain throughout the code.
//clearing the providers should force the site to always use English.
SiteLocalizationOptions.RequestCultureProviders.Clear();
HostingEnvironment = env;
...
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
//Add localization and translations
services.AddLocalization(options => options.ResourcesPath = "Resources");
services.Configure<RequestLocalizationOptions>(options =>
{
options.SupportedCultures = SiteLocalizationOptions.SupportedCultures;
options.SupportedUICultures = SiteLocalizationOptions.SupportedUICultures;
options.DefaultRequestCulture = SiteLocalizationOptions.DefaultRequestCulture;
});
services.AddDevExpressControls();
services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver())
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization(options =>
{
options.DataAnnotationLocalizerProvider = (type, factory) => factory.Create(typeof(SiteResource));
})
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver())
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options => options.LoginPath = new PathString(Loginpath));
...
//config
...
services.Configure<DatabaseSettings>(Configuration.GetSection("Database"));
services.Configure<HtmlPageSettings>(Configuration.GetSection("HtmlPages"));
services.Configure<ReportSettings>(Configuration.GetSection("Reporting"));
services.Configure<FilesSettings>(Configuration.GetSection("Files"));
services.Configure<AdminSettings>(Configuration.GetSection("Administrator"));
LatContext.ConnectionString = ...;
CroContext.ConnectionString = ...;
if (HostingEnvironment.IsDevelopment())
{
//repositories
services.AddSingleton<IUserRepository, UserRepository>();
services.AddSingleton<IStoredProcedures, StoredProcedures>();
//services
services.AddScoped<ILoginService, LoginService>();
}
else if (HostingEnvironment.IsEnvironment("Mock"))
{
//repositories
//No need to add repositories, since they are not used when the services are mocked
//services
services.AddScoped<ILoginService, MockLoginService>();
}
else //production
{
//repositories
services.AddSingleton<IUserRepository, UserRepository>();
services.AddSingleton<IStoredProcedures, StoredProcedures>();
//services
services.AddScoped<ILoginService, LoginService>();
}
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else if (env.IsEnvironment("Mock"))
{
}
else //production
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseDefaultFiles();
app.UseStaticFiles();
//app.UseStaticFiles(new StaticFileOptions
//{
// FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "node_modules")),
// RequestPath = "/node_modules"
//});
app.UseCookiePolicy();
app.UseAuthentication();
app.UseRequestLocalization(SiteLocalizationOptions);
...
app.UseDevExpressControls();
app.UseMvc(mvcRoutes =>
{
...
});
}
}
}

Example ASP.Net Core Breeze server with angular/breeze client code?

Is there example code of a breeze/angular client app using ASP.Net Core Breeze server?
It looks like there are the following Nuget packages:- Breeze.AspNetCore.NetCore and Breeze.Composite.AspNetCore.EF6
It would be really helpful to have the TempHire example using this technology.
Can you point me in the right direction? re. frontend/backend code example
Any help appreciated.
This is a bit of a journey because right now there are a lot of moving parts. I have had some success in getting this to work but there are some limitations for example i cannot use .expand('entityName') on the client.
I am using .NET CORE 3.0 preview with Entity Framework Core. I have attached an image of all the dependencies i have installed. Not all of them are required but probably used in a API project.
The most important parts of the below code snippet are to setup the NewtonsoftJson settings.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddNewtonsoftJson(options =>
{
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
//THE BELOW LINE IS IMPORTANT OTHERWISE IT WILL CAMELCASE TO THE SERVER
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
//THE BELOW LINE PREVENTS LOOPING ENTITY REFs
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
var connection = #"Server=tcp:XXXXX.database.windows.net,1433;Initial Catalog=DBNAME;Persist Security Info=False;User ID=XXX;Password=XXXXX;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;";
//THIS IS WHERE YOU ARE GOING TO MAKE YOUR CONTEXT INJECTABLE
services.AddDbContext<YOURCONTEXTContext>(options => options.UseSqlServer(connection, x => x.UseNetTopologySuite()));
var appSettingsSection = Configuration.GetSection("AppSettings");
services.Configure<AppSettings>(appSettingsSection);
// configure jwt authentication
var appSettings = appSettingsSection.Get<AppSettings>();
var key = Encoding.ASCII.GetBytes(appSettings.Token);
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => {
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
Then you need to setup your breeze controller:
using Microsoft.AspNetCore.Authorization;
using System.Linq;
using HB.Data.Models;
using Microsoft.AspNetCore.Http;
using System.Security.Claims;
using System;
using Microsoft.AspNetCore.Mvc;
using Breeze.AspNetCore;
using HB.API.Manager;
using HB.BusinessFacade.Business;
using GeoAPI.Geometries;
using NetTopologySuite.Geometries;
using Breeze.Persistence;
using System.Threading.Tasks;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
namespace HB.API.Controllers
{
[BreezeQueryFilter]
[Route("api/[controller]/[action]")]
public class BreezeController : ControllerBase
{
private YOURCONTEXTContext _context;
private hbPersistenceManager PersistenceManager;
string UserID;
public BreezeController(YOURCONTEXTContext context, IHttpContextAccessor httpContextAccessor)
{
this._context = context;
PersistenceManager = new hbPersistenceManager(context);
//this.UserID = httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
}
[HttpGet]
public string Metadata()
{
return PersistenceManager.Metadata();
}
}
And then just a little helper that i use for the PersistenceManager
using HB.Data.Models;
using Breeze.Persistence.EFCore;
namespace HB.API.Manager
{
public class hbPersistenceManager : EFPersistenceManager<YOURCONTEXTContext>
{
public hbPersistenceManager(YOURCONTEXTContext dbContext) : base(dbContext) { }
}
}
Please see this example: https://github.com/Breeze/northwind-demo
It is a full working example with a .NET Core 2.2 backend and Angular 8 front end, and includes TypeScript class generation so that the client-side TypeScript model matches the server-side C# model and database.
The example repo includes steps to create the entire app from scratch.

How to configure Odata api for show result from table or stored procedure

I am going to create an Odata api in asp.net mvc 4 for get data from new table. when I call the Odata method and use debug in the code It shows me data properly. But when it comes to browser, it shows empty screen.
There is no error shown in the code.
this is my Odata method :
[Queryable]
public HCPData GetHCPData([FromODataUri] int key)
{
// return SingleResult.Create(db.HCPDatas.Where(hcpdata => hcpdata.Id == key));
IQueryable<HCPData> result = db.HCPDatas.Where(p => p.CompanyId == key);
return result.FirstOrDefault();
}
this is my WebApiConfig method:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
//var entitySetConfiguration1 = modelBuilder.EntitySet<Job>("Job");
var entitySetConfiguration1 = modelBuilder.EntitySet<HCPData>("HCPData");
var customer = modelBuilder.EntityType<HCPData>();
modelBuilder.EntitySet<HCPData>("HCPData");
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: null,
model: modelBuilder.GetEdmModel());
}
When I checked the console of empty screen in browser it shows an error: "NetworkError: 406 Not Acceptable - http://localhost:50369/HCPData?key=11"
Please let me know the solution of the issue. Thanks in advance.
What's the result if you change the controller as follows:
public class HCPDataController : ODataController
{
[EnableQuery]
public HCPData GetHCPData([FromODataUri] int key)
{
...
}
}
[My Sample]
Because, at my side, if I implement the controller as follows, it can work:
[EnableQuery]
public HCPData GetHCPData([FromODataUri] int key)
{
var data = new HCPData
{
CompanyId = 2,
Name = "Key = " + key
};
return data;
}
Example:
Let me issue the following request:
I can get the following response:
{
"#odata.context":"http://localhost:62591/odata/$metadata#HCPData/$entity","CompanyId":2,"Name":"Key = 11"
}

Owin Odata Web API Self Host 406 Error

I'm trying to create an owin self host webapi with odata support.
I added all the dependencies and set everything up, when i call the get method (just by surfing to it with chrome).
The breakpoint i put on the GET gets called and returns without an exception.
But chrome just returns a blank screen, no http errors are found in the console of chrome.
When i do this in IE10 (yes old version, but i am not allowed to update it) i get 406 (Not Acceptable).
This is my Startup.cs code :
public void Configuration(IAppBuilder appBuilder)
{
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
//config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
//config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/xml"));
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: null,
model: builder.GetEdmModel());
appBuilder.UseWebApi(config);
}
This is my controller code, just a simple GET.
public class ProductsController : ODataController
{
ProductsContext db = new ProductsContext();
[EnableQuery]
public IQueryable<Product> Get()
{
try
{
return db.Products;
}
catch (System.Exception ex)
{
string x = "y";
return db.Products;
}
}
}
db.Products is an empty table for now, but this should still return an empty array right ?
Any help is greatly appreciated!
Thanks.
Thanks Fan Ouyang for the link, this has helped me resolve my issue!
Now i'm using the following code :
Owin Startup
var config = new HttpConfiguration();
config.MapODataServiceRoute(routeName: "OData", routePrefix: "odata", model: GetEdmModel());
appBuilder.UseWebApi(config);
GetEdmModel Function
private IEdmModel GetEdmModel()
{
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.EntitySet<Customer>("Customers");
return modelBuilder.GetEdmModel();
}
Controller GET
public PageResult<Customer> Get(ODataQueryOptions<Customer> queryOptions)
{
IQueryable results = queryOptions.ApplyTo(CustomerList.AsQueryable());
return new PageResult<Customer>(results as IEnumerable<Customer>, Request.ODataProperties().NextLink, CustomerList.Count);
}

Resources