This question already has answers here:
Angular routing not working on Netlify on page refresh
(5 answers)
Closed 4 years ago.
When clicking any links within my website on my serve of it, they work. However, after using ng build, none of the page links work. The website is: hiphost.co.za if you would like to test it yourself and see.
here is the code for my router:
RouterModule.forRoot([
{
path: '',
redirectTo: '/home',
pathMatch: 'full'
},
{
path: 'home',
component: HomeComponent,
pathMatch: 'full'
},
{
path: 'terms-and-conditions',
component: TermsAndConditionsComponent
},
{
path: 'privacy',
component: PrivacyPolicyComponent
},
{
path: 'about',
component: AboutComponent
},
{
path: 'contact',
component: ContactComponent
},
{
path: 'team',
component: TeamComponent
},
{
path:'safety',
component: SafetyComponent
}
]
)
So when you go to hiphost, it automatically redirects to /home, and then no links from there will work
All the request of routing is being handled by server instead of your app thus giving 404.
Easiest solution of it will be to direct your server to redirect all your requests to index.html so that your angular router can handle it.
In production, angular apps are hosted by a web server. SO when you are redirecting to any nested view. the web server does not recognize the path & throws 404 error.
Kindly follow this link to know how to tell web server to navigate to the nested view.
Rewriting URL for angular app in production
you need this on your web.config file
<system.webServer>
<rewrite>
<rules>
<rule name="AngularJS Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
you also need to add this on your index.html.
<base href="/">
Related
I have a site deployed using github page and sometime i get a 404 error, this also happend in localhost using ng serve --open
If you try to go on this page for the first time, you may have a 404 error : https://maximegillot.github.io/formation/kafka
But if you go to home page : https://maximegillot.github.io/ and manualy navigate to /formation/kafka you probably wont have any problems ...
I also have this problem when my site is deployed using ng serve --open
I feel like this problem is random and i dont know where to start investigating.
To deploy i just use ng build --aot --vendor-chunk --common-chunk --delete-output-path --build-optimizer and publish /dist/mgi-site/* on github : https://github.com/MaximeGillot/MaximeGillot.github.io
my index.html
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Gillot Maxime</title>
<base href="/">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,700" rel="stylesheet" type="text/css"/>
<link href="https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic" rel="stylesheet"
type="text/css"/>
<link rel="icon" type="image/x-icon" href="assets/favicon.ico"/>
<script src="https://use.fontawesome.com/releases/v5.15.3/js/all.js" crossorigin="anonymous">
...
</head>
<body>
<app-root></app-root>
</body>
</html>
file app-routing.module.ts :
const routes: Routes = [
{path: '', redirectTo: 'home', pathMatch: 'full'},
{path: 'formation/nifi', component: FormationNifiComponent},
{path: 'formation/kafka', component: FormationKafkaComponent},
{path: 'home', component: MainComponent},
{path: 'cv', component: CvComponent},
{path: 'projets', component: ProjetComponent}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {
}
Angular is a single page application and when deployed without using the #, the hosting site tries to find the path locally as a folder path which doesn't exist and the reason why you get the 404 error.
If you don't have one already, you will need a web.config file set up to handle the redirects.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Angular Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="./index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
SOURCES:
https://angular.io/guide/deployment#server-configuration
https://indepth.dev/posts/1239/deploy-an-angular-application-to-iis
I've searched thoroughly but cannot find a solution to this issue in my particular circumstance.
Cross-domain service calls using Fiddler (POST) execute correctly and the data is received. However, through the browser (Chrome) I am getting the message 'preflight has invalid HTTP status code 404'
I have a Web API application and have installed CORS and ensured the following is present in the web.config file:
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
</system.webServer>
Here is the Ajax call:
var secretKey = 'difusod7899sdfiertwe08wepifdfsodifyosey',
url = 'http://api.intrinsic.co.uk/api/v1/PTS/ActiveDrivers?api_key=098werolllfWnCbPGAuIXVOJidDHRfYcgxImMlxTXopuekXrSOqOWzEAIdeNTWGPQPpyHxgVGsFysGFKPzq';
jQuery.ajax ({
url: url,
type: "POST",
data: JSON.stringify({ secretKey: secretKey}),
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function(data){
var content = "<table class=\"container\"><thead><tr><th>Driver Number</th><th>Timestamp</th><th>VRN</th><th>Latitude</th><th>Longitude</th><th>Track Link</th></tr></thead><tbody>";
$.each(data.ActiveDrivers.DriverLocationStatus, function (index, element) {
content += "<tr><td>" + element.DriverNumber + "</td>";
content += "<td>" + dateFormat(element.Timestamp, "d/m/yy") + " " + dateFormat(element.Timestamp, "h:MM TT") + "</td>";
content += "<td>" + element.VRN + "</td>";
content += "<td>" + element.CurrentLatitude + "</td>";
content += "<td>" + element.CurrentLongitude + "</td>";
content += "<td><a href=\"https://www.google.co.uk/maps/place//#" + element.CurrentLatitude + "," + element.CurrentLongitude + ",15z/\" target='_blank'>Track »</a></td></tr>";
});
content += "</tbody></table>";
$( "#result" ).html( content );
}
});
Obviously, works on the same domain perfectly and, as mentioned, it works using Fiddler.
I'm certain it is the browser's preflight OPTIONS check that is failing for content-type of 'application/json' but I'm not sure how to fix it.
Is there something missing in the web.config file that I should add?
I have tried removing 'content-type' with no affect.
I had hoped this article would solve the issue (it seemed promising) but the same error is encountered:
XMLHttpRequest cannot load [URL]. Response for preflight has invalid HTTP status code 404
Thanks but getting 405 error,after the above config changes.
Finally it works after adding below code in web api Global.asax file
protected void Application_BeginRequest(Object sender, EventArgs e)
{
//HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
I finally got this to work.
This article 'WebAPI with CORS – IIS Intercepts OPTIONS Verb' informed my thinking. An image showed where, in IIS, the OPTIONS handler mapping appeared and why, within the web.config we needed to remove it to ensure IIS did not intercept.
When I took a look at IIS that handler WAS NOT there. I then took a look at the linked article 'Can't set HttpHandler order using Web.Config unless a «clear» tag exists' and saw that, in this article, after removing the OPTION handler, it was then explicitly added within the web.config.
As I could not see the OPTION handler in IIS, I too added it to the web.config file and all suddenly worked. It appeared that this addition is what was needed.
The final web.config handlers section looks as follows (notice I decided to keep the initial 'remove' just in case this caused problems if I migrated to a different web server in the future).
<system.webServer>
<handlers>
<remove name="WebDAV"/>
<remove name="OPTIONSVerbHandler"/>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="ProtocolSupportModule" requireAccess="None" responseBufferLimit="4194304" />
</handlers>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS" />
</customHeaders>
</httpProtocol>
</system.webServer>
This worked for me.
In Global.asax
protected void Application_BeginRequest(Object sender, EventArgs e)
{
//HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
In Web.config
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*"/>
<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS"/>
<add name="Access-Control-Allow-Headers" value="Content-Type"/>
</customHeaders>
</httpProtocol>
rebuild and hey presto.
I have a similar setup that was showing 404 errors and 500 errors as I was attempting to get CORS running on my web service. My fix basically used Hussain's solution, but as I cleaned up my fix, I noted that only one Response line was needed, and I was able to keep the original web handlers in the web.config, and did NOT need to move all of the response handlers into code.
Basically, my fix includes this ONE MAJOR FIX in my ApplicationOnBeginRequest handler:
private void ApplicationOnBeginRequest( object sender, EventArgs eventArgs )
{
...
if ( context.Request.HttpMethod == "OPTIONS" )
response.End();
}
and these handlers in my web.config:
<system.webServer>
<!--Other handlers/modules ...-->
<httpProtocol>
<customHeaders>
<clear />
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Credentials" value="true" />
<add name="Access-Control-Allow-Headers" value="Content-Type,Accept" />
<add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS" />
</customHeaders>
</httpProtocol>
</system.webServer>
Sorry I couldn't send this note as a comment to Hussain's answer.
For those using .NET Core 3.1, here is a COMPLETE solution (front-end to back-end):
My problem: When I enabled the windows authentication on my web API, I could not do fetch calls from my react app to my .NET Core 3.1 web API, CORS was freaking out. With Anonymous authentication it worked, but not when windows authentication is enabled.
1.launchSettings.json
this will be used only for your dev environnment, make sure windows auth is also enabled in IIS on your prod server.
{
"iisSettings": {
"windowsAuthentication": true,
"anonymousAuthentication": false,
"iisExpress": {
"applicationUrl": "http://localhost:58747",
"sslPort": 0
}
},
{... more settings if any}
}
2.Startup.cs:
CORS policy is enabled here. The order of methods is important here. Also, you don't need to set those in a web.config
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", //give it the name you want
builder =>
{
builder.WithOrigins( "http://localhost:3000", //dev site
"production web site"
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
//database services here
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
// global policy same name as in the ConfigureServices()
app.UseCors("CorsPolicy");
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
3.Controller(s):
using Microsoft.AspNetCore.Cors;
... your other usings
namespace ProjectTest.Controllers
{
[ApiController]
[EnableCors("CorsPolicy")] //THIS HERE needs to be the same name as set in your startup.cs
[Route("[controller]")]
public class FooController:Controller
{
[HttpGet("getTest")]
public JsonResult GetTest()
{
return Json("bar");
}
}
}
4.React Component fetch call example:
The "credential: 'include'" is the secret
await fetch('http://localhost:3000/Foo/getTest', {
method: 'GET',
credentials: 'include'
}).then(resp => resp.json());
For asp core use this code in Startup.cs in Configure procedure. I used for 2.0 version but i think it should work with older too
app.UseCors(builder => {
builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
});
This helped me too, I had CORS configured in web.config already
protected void Application_BeginRequest(Object sender, EventArgs e)
{
//HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
I'm trying to get a Sitecore 8 project going with MVC and I am getting the following error:
Compiler Error Message: CS0103: The name 'RenderLink' does not exist in the current context
I have as references (from the nuget packages)
Castle.Core
Glass.Mapper
Glass.Mapper.Sc
Glass.Mapper.Sc.Mvc
I've tried a few things with the views/web.config. Perhaps there are clashes?
<namespaces>
<add namespace="Sitecore.Mvc" />
<add namespace="Sitecore.Data.Items" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Optimization"/>
<add namespace="System.Web.Routing" />
<add namespace="TDSExample.Web" />
<add namespace="TDSExample.Entities.Ids" />
<add namespace="Glass.Mapper.Sc" />
</namespaces>
I've cleared the Sitecore cache. I'm not sure what I've missed.
Here is a cut down version of the view/rendering:
#model Glass.Mapper.Sc.Web.Mvc.GlassView
<TDSExample.Entities.Templates.Header.Header>
#using Glass.Mapper.Sc #{ Layout = null; var dataSource = Sitecore.Context.Database.GetItem(Sitecore.Mvc.Presentation.RenderingContext.Current.Rendering.DataSource) ?? Sitecore.Context.Item; }
<h1>#Model.Editable(x => x.Title, dataSource)</h1>
<p>
#Model.Editable(x => x.Subtitle, dataSource)
</p>
#RenderLink(x => x.ReadMoreLink, dataSource, new { #class = "read-more" })
Here is a cut down version of the rendering:
#model Glass.Mapper.Sc.Web.Mvc.GlassView
<TDSExample.Entities.Templates.Header.Header>
#using Glass.Mapper.Sc #{ Layout = null; var dataSource = Sitecore.Context.Database.GetItem(Sitecore.Mvc.Presentation.RenderingContext.Current.Rendering.DataSource) ?? Sitecore.Context.Item; }
<h1>#Model.Editable(x => x.Title, dataSource)</h1>
<p>
#Model.Editable(x => x.Subtitle, dataSource)
</p>
#RenderLink(x => x.ReadMoreLink, dataSource, new { #class = "read-more" })
The test fields rendering just fine. I must be missing a reference somewhere. Putting "#using Glass.Mapper.Sc" or "#using Glass.Mapper.Sc/Mvc" stops VS highlighting it as an error.
I just can't see what I've missed. Any help is appreciated.
change this
#model Glass.Mapper.Sc.Web.Mvc.GlassView<TDSExample.Entities.Templates.Header.Header>
into this
#inherits Glass.Mapper.Sc.Web.Mvc.GlassView<TDSExample.Entities.Templates.Header.Header>
And access the methods on the view instead of the model:
#Editable(m => m.Title)
#RenderLink(m => m.ReadMoreLink)
<!--this should work as well for links-->
#Editable(m => m.ReadMoreLink)
Added bonus: you should not have to set the layout to null. Make sure you do not have a _ViewStart.cshtml which could cause this.
Note: This question while similar to this one however it's about different issues.
It seems for whatever reason ServiceStack is not running/compiling Razor views and seems like a config issue however RazorRockstarts runs fine.
I'm using ServiceStack 4.0.11 and have compared against RazorRockstars runnning ServiceStack 4.0.8
In VS2013 I have created a new ASP.NET Website (Empty)
Install-Package ServiceStack
Install-Package ServiceStack.Razor
Added httpHandlers to web.config
Created AppHost and .Init() in Global.asax Application_Start.
AppHost.LoadPlugin(new RazorFormat());
Created /Services/HomeService.cs (inherited from ServiceStack.Service)
Created Home route in HomeService
Created /Views/Home/Home.cshtml
I run in debug on VS 2013 and all I get is the ServiceStack snapshot when going to /home. What am I missing?
/AppHost.cs
using Funq;
using ServiceStack;
using ServiceStack.Razor;
namespace SSTest
{
public class AppHost : AppHostBase
{
public AppHost() : base("SSTest", typeof(AppHost).Assembly) { }
public override void Configure(Container container)
{
LoadPlugin(new RazorFormat());
}
public static void Start()
{
new AppHost().Init();
}
}
}
/Global.asax
protected void Application_Start(object sender, EventArgs e)
{
AppHost.Start();
}
/Services/HomeService.cs
using ServiceStack;
namespace SSTest.Services
{
[Route("/home")]
public class Home
{
public string Name { get; set; }
}
[DefaultView("Home")]
public class HomeServices : Service
{
public object Get(Home request)
{
return new Home(){Name = "Here's home!"};
}
}
}
/Views/Home/Home.cshtml
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Home</title>
</head>
<body>
<div>
<h1>This is home!!</h1>
</div>
</body>
</html>
/Web.config
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web>
<httpHandlers>
<add path="*" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*" />
</httpHandlers>
<compilation debug="true" targetFramework="4.5">
<assemblies>
<add assembly="System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
<buildProviders>
<add extension=".cshtml" type="ServiceStack.Razor.CSharpRazorBuildProvider, ServiceStack.Razor" />
</buildProviders>
</compilation>
<httpRuntime targetFramework="4.5" />
</system.web>
<!-- Required for IIS 7.0 -->
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<add path="*" name="ServiceStack.Factory" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" />
</handlers>
</system.webServer>
<appSettings>
<add key="webPages:Enabled" value="false" />
</appSettings>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="ServiceStack.Razor.ViewPage">
<namespaces>
<add namespace="ServiceStack" />
<add namespace="ServiceStack.Html" />
<add namespace="ServiceStack.Razor" />
<add namespace="ServiceStack.Text" />
<add namespace="ServiceStack.OrmLite" />
<add namespace="SSTest" />
<add namespace="SSTest.Services" />
</namespaces>
</pages>
</system.web.webPages.razor>
</configuration>
I know mythz has solved your problem, but something else to check for future readers with the same problem:
Make sure your *.cshtml files are copied to the output directory. For whatever reason, mine weren't, thus ServiceStack couldn't find them and all I got was the snapshot like yourself.
I'm not sure if this is related to using a self-hosted console application instead of a web project.
Inside Configure() plugins should be loaded with:
Plugins.Add(new RazorFormat());
In ServiceStack.Razor Layout = null, suggests to use the default layout template Views\_Layout.cshtml, you can choose not use any template with Layout="" instead.
If you don't have OrmLite installed then you want to remove the ServiceStack.OrmLite namespace from being included in all Razor pages by removing it from your Web.config:
<add namespace="ServiceStack.OrmLite" />
Your view should be located in /Views/Home.cshtml instead of /Views/Home/Home.cshtml.
I was having the exact same issue! With the current ServiceStack VS template (as of April 1, 2015 and no this isn't an April Fools joke!), the following line will mess things up if you're running a self-hosted service:
WebHostPhysicalPath = Path.GetFullPath(Path.Combine("~".MapServerPath(), "..", "..")),
This is within your AppHost.cs file inside of the Configure(Container) function within the SetConfig(new HostConfig { /* ... here ... */ } ); block.
Comment out the entire WebHostPhysicalPath = ... line and re-run your application.
A better fix than simply commenting it out is to set the correct directory which is either your actual bin directory via:
WebHostPhysicalPath = Path.GetFullPath("~".MapServerPath()),
Or, if you have a specific build architecture (ie. x86 or x64 instead of AnyCPU), you likely have a third layer of folders. So change the WebHostPhysicalPath to this:
WebHostPhysicalPath = Path.GetFullPath(Path.Combine("~".MapServerPath(), "..", "..", "..")),
I'm using a ODataController to return data to the breeze dataservice, this is the dataservice
app.dataservice = (function (breeze) {
breeze.config.initializeAdapterInstances({ dataService: "OData" });
var manager = new breeze.EntityManager('/api/v1/');
return {
getRecipePage: getRecipePage
};
function getRecipePage(skip, take, searchText) {
var query = breeze.EntityQuery
.from("Recipes")
.orderBy("Name")
.skip(skip).take(take)
.inlineCount(true);
if (searchText) {
query = query.where("Name", "contains", searchText);
}
return manager.executeQuery(query);
}
})(breeze);
when calling the getRecipePage function in my controller, it seems to return data properly, but the exceptions is strange
getDataFunction(skip, take)
.then(function (largeLoad) {
$scope.setPagedData(largeLoad, currentPage, pageSize);
})
.fail(function (e) {
debugger;
});
The e variables has the message "; ", which makes no sense. The status is "200 OK" which is good.
The body contains my two entities and the url appers correct "/api/v1/Recipes?$orderby=Name&$top=2&$inlinecount=allpages", if I navigate to it, the json looks good:
{
"$id": "1",
"$type": "Breeze.WebApi2.QueryResult, Breeze.WebApi2",
"Results": [
{
"$id": "2",
"$type": "RecipeBook.Web.Angular.Models.RecipeBook.Recipe, RecipeBook.Web.Angular",
"Name": "1 Boiled Water",
"Description": "6 Steamy goodness!",
"Id": 1
},
{
"$id": "3",
"$type": "RecipeBook.Web.Angular.Models.RecipeBook.Recipe, RecipeBook.Web.Angular",
"Name": "2 Hot Chocolate",
"Description": "5 Chocolatey Chocolateness!",
"Id": 2
}
],
"InlineCount": 6
}
...what is this error? Lastly, here is the stack:
Error
at createError (http://localhost:62576/Scripts/breeze.debug.js:15182:22)
at http://localhost:62576/Scripts/breeze.debug.js:14971:40
at http://localhost:62576/Scripts/datajs-1.1.1.js:1671:17
at XMLHttpRequest.odata.defaultHttpClient.request.xhr.onreadystatechange (http://localhost:62576/Scripts/datajs-1.1.1.js:2587:25)
Thoughts as to what is going on???
EDIT:
After a ton of digging, I've somewhat narrowed down the issue to be related to the handler that reads the response. In datajs-1.1.1.js ~line 8100 there is a dispatchHandler function. I have a requestOrResponse that came back from the OData call:
It has a body property with the above json text. The data property is undefined however, but I think that's what it's trying to translate the body into...and is looking for a handler to do so. It's statusCode is 200, and statusText is OK. But the method doesn't find an appropriate handler and throws:
throw { message: "no handler for data" };
...this appears to be where the error originates. I just have no clue what's not setup correctly so that I can remedy the situation.
EDIT2:
It might actually be caused because the metadata (xml) isn't being parsed correctly..., this is what it looks like (taken from the datajs handlerRead function while debugging)
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
<edmx:DataServices m:DataServiceVersion="3.0" m:MaxDataServiceVersion="3.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<Schema Namespace="RecipeBook.Web.Angular.Models.Recipe" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
<EntityType Name="Recipe">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false" />
<Property Name="Name" Type="Edm.String" />
<Property Name="Description" Type="Edm.String" />
<Property Name="Steps" Type="Collection(Edm.String)" />
<NavigationProperty Name="Ingredients" Relationship="RecipeBook.Web.Angular.Models.Recipe.RecipeBook_Web_Angular_Models_Recipe_Recipe_Ingredients_RecipeBook_Web_Angular_Models_Recipe_RecipeIngredient_IngredientsPartner" ToRole="Ingredients" FromRole="IngredientsPartner" />
</EntityType>
<EntityType Name="RecipeIngredient">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="Edm.Int32" Nullable="false" />
<Property Name="IngredientId" Type="Edm.Int32" Nullable="false" />
<Property Name="Quantity" Type="Edm.Int32" Nullable="false" />
<Property Name="UnitOfMeasureId" Type="Edm.Int32" Nullable="false" />
<Property Name="Notes" Type="Edm.String" />
</EntityType>
<Association Name="RecipeBook_Web_Angular_Models_Recipe_Recipe_Ingredients_RecipeBook_Web_Angular_Models_Recipe_RecipeIngredient_IngredientsPartner">
<End Type="RecipeBook.Web.Angular.Models.Recipe.RecipeIngredient" Role="Ingredients" Multiplicity="*" />
<End Type="RecipeBook.Web.Angular.Models.Recipe.Recipe" Role="IngredientsPartner" Multiplicity="0..1" />
</Association>
<EntityContainer Name="Container" m:IsDefaultEntityContainer="true">
<EntitySet Name="Recipes" EntityType="RecipeBook.Web.Angular.Models.Recipe.Recipe" />
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
EDIT3:
...so, if I use OData, as my dataService I need json metadata found at $metadata. If I use WebAPI it looks for metadata at /Metadata, and this can be Edmx or json. However, my metadata is returned as Edmx at $metadata ... which is the one thing not supported?
http://www.breezejs.com/documentation/breeze-metadata-details
I'm about to throw all this out (angular, breeze, odata) and just do it the old way.
Edit4:
This isn't a fix, but if I turn off metadata it "works"...so my issue is definitely related to Metadata not loading properly.
var dataService = new breeze.DataService({
serviceName: "/api/v1/",
hasServerMetadata: false
});
It looks like you are using Web API. Consider that you could decorate your controllers with the [BreezeController] attribute and instead of specifying OData you could use webApi which extends the configuration a bit. It's worth trying.
Also you probably need to configure the Breeze adapter to use backingStore which pairs well with Angular. - http://www.breezejs.com/samples/todo-dataservice (this link has some helpful tips to guide you through setting up Breeze to work well with Angular)
Last, remember that setting up any library the first time you use it always seems more difficult than it really is. Once you get it configured you almost never touch configuration again and instead Breeze just works and is really awesome.
EDIT
Check this link which has a brief walk-thru on Breeze, Angular, OData, and Web API - http://sravi-kiran.blogspot.com/2013/11/UsingBreezeJsToConsumeAspNetWebApiODataInAnAngularJsApplication.html
Another good 'How do I...' answer here by Ward -
How to consume OData service with Html/Javascript?