I have added a Web API feature to an ASP.NET MVC app and want to use attribute routing. When running the site in Visual Studio 2015, I can enter URLs in the browser address bar and get the methods on my controller to work. Once I move the site to IIS, all I get is 404 responses. I have tried many code changes with no luck.
The BuilderApiController file is in a WebAPI/v1/Controllers folder. Will attributes on the controller be found here?
namespace Hds.Edsi.WebAPI.V1.Controllers
{
[System.Web.Http.RoutePrefix("api/v1/builder")]
public class BuilderApiController : BaseApiController
{
[System.Web.Http.Route("GetExternalOrganizationID/{envisionOrgID}")]
[System.Web.Http.HttpGet]
public HttpResponseMessage GetExternalOrganizationID(string envisionOrgID)
{
WebApiConfig.cs file. Standard stuff. If I am using attribute routing, do I need the config.Routes.MapHttpRoute part? I have tried it with and without.
If I need it, what is the purpose of config.MapHttpAttributeRoutes()? When I look at GlobalConfiguration,Configuration._routes after Register is called, none of the attribute routing defined routes are there. Should they be?
namespace Hds.Edsi.WebAPI
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
/*
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/v1/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
*/
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new StringEnumConverter());
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
Components.Automapper.CreateMaps();
// Requrired for managing AppDomain teardown - IRegisteredObject
MonitorManager.RegisterInstance();
}
IIS Express:
http://localhost:8181/api/v1/builder/GetExternalOrganizationID/123.123.123.123.1234 returns a JSON object as I would expect.
IIS:
http://my server/api/v1/builder/GetExternalOrganizationID/123.123.123.123.1234 returns a 404
I am guessing that I am missing something simple here or don't understand how attribute routing works.
Added
Here is the system.webServer section from web.config:
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
</modules>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*" verb="*" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
</handlers>
</system.webServer>
As per as i know, if it's not working properly on your IIS, then that is an IIS error, not an ASP.NET error so this doesn’t actually come from ASP.NET’s routing engine but from IIS’s handling of expressionless URLs.
You can try with adding runAllManagedModulesForAllRequests to your web.config
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="ScriptCompressionModule" type="Westwind.Web.ScriptCompressionModule,Westwind.Web" />
</modules>
</system.webServer>
In detail you can refer Rick Strahl's Web Log ASP.NET Routing not working on IIS 7.0
Hope this helps!
I am trying to create an additional access token for a user within my spring boot application. I do not know their password but the user is authorized to the application. From what I can see I would need to call something like
OAuth2AccessToken accessToken = tokenServices.createAccessTokenForUser(authenticationRequest, user);
Where tokenServices is presumably an instance of DefaultTokenServices. The question is how do I get a reference to the configured token services? I see that this is wired into AuthorizationServerEndpointsConfigurer but I cannot autowire this in. I am using JWT for authentication so really looking for a way to generate a JWT token.
Was trying to implement the flow outlined in Spring OAuth2 - Manually creating an access token in the token store
In my spring-security-config.xml i have this:
<bean id="tokenServices" class="de.hybris.platform.ycommercewebservices.oauth2.token.provider.HybrisOAuthTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="refreshTokenValiditySeconds" value="2592000" />
<!-- 60*60*24*30 = 30d -->
<property name="accessTokenValiditySeconds" value="43200" />
<!-- 60*60*12 = 12h -->
</bean>
Where i can configure my customized tokenServices
public class HybrisOAuthTokenServices extends DefaultTokenServices{
#Override
public OAuth2AccessToken createAccessToken(final OAuth2Authentication authentication) throws AuthenticationException{
try{
return super.createAccessToken(authentication);
}catch (final ModelSavingException e) {
//in case when other client was faster in saving access token - try to get token again
return super.createAccessToken(authentication);
}catch (final ModelRemovalException e) {
//in case when other client was faster in removing expired token - try to get token again
return super.createAccessToken(authentication);
}
}
}
I am trying to implemente code First Migrations with Oracle.ManagedDataAccess 6.121.1.0 provider, but with no success at all.
As I am receiving a ORA-code, I am assuming that the connection are been opened successfully. But the Migrations are failing because, maybe, the provider are behaving as a SQL Server, instead of Oracle. I think that beacause it is traying to use 'dbo' as default schema.
Here is my web.config settings:
<configuration>
<configSections>
<section name="entityFramework"
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
requirePermission="false" />
<section name="Oracle.ManagedDataAccess.Client"
type="OracleInternal.Common.ODPMSectionHandler, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
</configSections>
<entityFramework>
<contexts>
<context type="MyProject.Context.MainContext, MyProject.Context">
<databaseInitializer type="MyProject.Context.Config.ContextInitializer, MyProject.Context" />
</context>
</contexts>
<defaultConnectionFactory type="Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess" />
<providers>
<provider invariantName="Oracle.ManagedDataAccess.Client"
type="Oracle.ManagedDataAccess.EntityFramework.EFOracleProviderServices, Oracle.ManagedDataAccess.EntityFramework, Version=6.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
</providers>
</entityFramework>
<system.data>
<DbProviderFactories>
<remove invariant="Oracle.ManagedDataAccess.Client" />
<add name="ODP.NET, Managed Driver"
invariant="Oracle.ManagedDataAccess.Client"
description="Oracle Data Provider for .NET, Managed Driver"
type="Oracle.ManagedDataAccess.Client.OracleClientFactory, Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
</DbProviderFactories>
</system.data>
<connectionStrings>
<add name="MainContext"
providerName="Oracle.ManagedDataAccess.Client"
connectionString="Data Source=OracleServer:1521/BRSYSDS;User ID=USER;Password=PASSWORD;" />
</connectionStrings>
<!-- other settings -->
</configuration>
Here the Stacktrace:
[OracleException (0x77e): ORA-01918: user 'dbo' does not exist]
OracleInternal.ServiceObjects.OracleCommandImpl.VerifyExecution(OracleConnectionImpl connectionImpl, Int32& cursorId, Boolean bThrowArrayBindRelatedErrors, OracleException& exceptionForArrayBindDML, Boolean& hasMoreRowsInDB, Boolean bFirstIterationDone) +652
OracleInternal.ServiceObjects.OracleCommandImpl.VerifyExecution(OracleConnectionImpl connectionImpl, Int32& cursorId, Boolean bThrowArrayBindRelatedErrors, OracleException& exceptionForArrayBindDML, Boolean bFirstIterationDone) +39
OracleInternal.ServiceObjects.OracleCommandImpl.ExecuteNonQuery(String commandText, OracleParameterCollection paramColl, CommandType commandType, OracleConnectionImpl connectionImpl, Int32 longFetchSize, Int64 clientInitialLOBFS, OracleDependencyImpl orclDependencyImpl, Int64[]& scnFromExecution, OracleParameterCollection& bindByPositionParamColl, Boolean& bBindParamPresent, OracleException& exceptionForArrayBindDML, Boolean isFromEF) +7480
Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteNonQuery() +678
System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.b__0(DbCommand t, DbCommandInterceptionContext1 c) +10
System.Data.Entity.Infrastructure.Interception.InternalDispatcher1.Dispatch(TTarget target, Func3 operation, TInterceptionContext interceptionContext, Action3 executing, Action3 executed) +72
System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.NonQuery(DbCommand command, DbCommandInterceptionContext interceptionContext) +357
System.Data.Entity.Internal.InterceptableDbCommand.ExecuteNonQuery() +104
System.Data.Entity.Migrations.DbMigrator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement, DbInterceptionContext interceptionContext) +152
System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable1 migrationStatements, DbTransaction transaction, DbInterceptionContext interceptionContext) +82
System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable1 migrationStatements, DbConnection connection) +626
System.Data.Entity.Migrations.<>c__DisplayClass30.<ExecuteStatements>b__2e() +19
System.Data.Entity.Infrastructure.DefaultExecutionStrategy.Execute(Action operation) +9
System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable1 migrationStatements, DbTransaction existingTransaction) +194
System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable1 migrationStatements) +7
System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, XDocument targetModel, IEnumerable1 operations, IEnumerable1 systemOperations, Boolean downgrading, Boolean auto) +825
System.Data.Entity.Migrations.DbMigrator.AutoMigrate(String migrationId, VersionedModel sourceModel, VersionedModel targetModel, Boolean downgrading) +564
System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable1 pendingMigrations, String targetMigrationId, String lastMigrationId) +404
System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration) +447
System.Data.Entity.Migrations.<>c__DisplayClassc.b__b() +13
System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase) +422
System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration) +78
System.Data.Entity.Internal.DatabaseCreator.CreateDatabase(InternalContext internalContext, Func3 createMigrator, ObjectContext objectContext) +89
System.Data.Entity.Internal.InternalContext.CreateDatabase(ObjectContext objectContext, DatabaseExistenceState existenceState) +116
System.Data.Entity.Database.Create(DatabaseExistenceState existenceState) +218
System.Data.Entity.DropCreateDatabaseAlways1.InitializeDatabase(TContext context) +137
I had the same problem and it was resolved by Thiago Lunardi's response. Thank you. I didn't have enough reputation to vote up your response. To mention here, I succeeded after setting my schema name in UPPERCASE.
Put this in your Context file under your new dbContext class, like this:
public partial class MyAppContext : DbContext
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("UPPERCASE_SCHEMA_NAME");
...
I solve this just setting the default schema at modelBuilder
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("MyOracleSchema");
// ...
}
Setting default schema didn't work for me.
I found the solution by customizing migrations history table to set a different schema.
You can find a solution here: LINK.
User Dbo also comes in case of missing fully qualified name of the Table. Which may not map to the right Table in the database.
If you use Automatic Migrations (as I was), then note: modelBuilder.HasDefaultSchema whouldn't help until you switch to explicit migrations.
From Oracle Docs:
Code First Automatic Migrations is limited to working with the dbo schema only. Due to this limitation it is recommended to use code-based migrations, that is, add explicit migrations through the Add-Migration command
in Code First you can use the DataAnnotations for Table .
[Table("Emplpoyee",Schema="YOUR SCHEMA NAME"]
I had the same problem. I placed my schema name in OnModelCreating() method.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("MyOracleSchema");
// ...
}
But, setting schema name in UPPERCASE didn't work for me. I added below mentioned code in Confifuration.cs and it worked !!
Go to Migrations -> Configuration.cs
class Configuration : DbMigrationsConfiguration<CodeFirstOracleProject.Context>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
var historyContextFactory = GetHistoryContextFactory("Oracle.ManagedDataAccess.Client");
SetHistoryContextFactory("Oracle.ManagedDataAccess.Client",
(dbc, schema) => historyContextFactory.Invoke(dbc, "YourSchemaName"));
}
}
In my case writing schema name in Uppercase wasn't sufficient I had to use toUpper() function as such :
modelBuilder.HasDefaultSchema("YOURSCHEMA".ToUpper())
alongside adding
public Configuration()
{
AutomaticMigrationsEnabled = false;
var historyContextFactory = GetHistoryContextFactory("Oracle.ManagedDataAccess.Client");
SetHistoryContextFactory("Oracle.ManagedDataAccess.Client",
(dbc, schema) => historyContextFactory.Invoke(dbc, "YOURSCHEMA".ToUpper()));
}
removed the migrations and regenerating them fixed the issue.
As a beginner, the major issue I had with the answers here was, what does user 'dbo' has to do with schema name.
After researching, here is what I found.
In oracle, A Schema is a collection of database objects. A schema is owned by a database user and has the same name as the user.
The default schema for entity framework is however dbo, and you can override this as in the code listing below:
modelBuilder.HasDefaultSchema("YOURSCHEMA".ToUpper())
For oracle, "YOURSCHEMA" has to be the user_id for the database you are connected to.
Then you need to add the below to your configuration file
public Configuration()
{
AutomaticMigrationsEnabled = false;
var historyContextFactory = GetHistoryContextFactory("Oracle.ManagedDataAccess.Client");
SetHistoryContextFactory("Oracle.ManagedDataAccess.Client",
(dbc, schema) => historyContextFactory.Invoke(dbc, "YOURSCHEMA".ToUpper()));
}
Finally, delete the migration files generated and rerun Add-Migration again.
I hope this will help somebody.
I want to display a custom error page on authentication denial (I am using a pre-authenticated secnario) and also access denial from Spring Security 3.0.X
Understand we can use the following to perform this:
<beans:bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/error.jsp"/>
</beans:bean>
<beans:bean id="accessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<beans:property name="errorPage" value="/error.jsp"/>
</beans:bean>
but doing this results in a redirect and not a forward to the error page. Anyway to perform forward to an error page (so that we can set some attributes in the request)
Thanks
In my security-context.xml, for authentication failure I do like this (pay attention to the authentication-failure-url attribute):
<security:form-login login-page="/auth/login"
authentication-failure-url="/auth/login?error=true"
default-target-url="/mvc/home"
always-use-default-target="true" />
And for access denied I use this:
<security:access-denied-handler error-page="/auth/access-denied"/>
Both tags inside <security:http use-expressions="true">. For me works like a charm, I don't know why you are trying to configure it in the way you are doing when Spring provides such nice tags easy to use.
I don't know if it answers your question, I hope it helps.
EDIT:
Using the configuration provided above, means that you are using the default authentication failure handler (SimpleUrlAuthenticationFailureHandler) at the background. You can change the default behavior (which as default performs a redirect when a failed authentication is produced) by changing the attribute forwardToDestination value. This is what SimpleUrlAuthenticationFailureHandler does:
/**
* Performs the redirect or forward to the {#code defaultFailureUrl} if set, otherwise returns a 401 error code.
* <p>
* If redirecting or forwarding, {#code saveException} will be called to cache the exception for use in
* the target view.
*/
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
if (defaultFailureUrl == null) {
logger.debug("No failure URL set, sending 401 Unauthorized error");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed: " + exception.getMessage());
} else {
saveException(request, exception);
if (forwardToDestination) {
logger.debug("Forwarding to " + defaultFailureUrl);
request.getRequestDispatcher(defaultFailureUrl).forward(request, response);
} else {
logger.debug("Redirecting to " + defaultFailureUrl);
redirectStrategy.sendRedirect(request, response, defaultFailureUrl);
}
}
}
So I guess that I you declare your SimpleUrlAuthenticationFailureHandler in your security-context.xml and set the mentioned property value using the setUseForward(boolean forwardToDestination) method it should work. Could be something like:
<bean id="simpleUrlAuthenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="useForward" value="true">
</bean>
And then:
<security:form-login login-page="/auth/login"
authentication-failure-handler-ref="simpleUrlAuthenticationFailureHandler"
default-target-url="/mvc/home"
always-use-default-target="true" />
Good luck.
I have version 1.6 of the MvcMiniProfiler referenced (via Nuget) and have set everything up as described on the project homepage at http://code.google.com/p/mvc-mini-profiler/.
I have the following code in the Web.config:
<system.data>
<DbProviderFactories>
<remove invariant="MvcMiniProfiler.Data.ProfiledDbProvider" />
<add name="MvcMiniProfiler.Data.ProfiledDbProvider" invariant="MvcMiniProfiler.Data.ProfiledDbProvider" description="MvcMiniProfiler.Data.ProfiledDbProvider" type="MvcMiniProfiler.Data.ProfiledDbProviderFactory, MvcMiniProfiler, Version=1.6.0.0, Culture=neutral, PublicKeyToken=b44f9351044011a3" />
</DbProviderFactories>
</system.data>
(The project homepage has Version=1.5.0.0 - the NuGet package has since been updated)
I have the following code in the Global.asax (and connection string also defined in Web.config):
protected void Application_Start()
{
Log.Info("ReCoupon has started.");
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
var factory = new SqlConnectionFactory(ConfigurationManager.ConnectionStrings["ReCouponContext"].ConnectionString);
var profiled = new MvcMiniProfiler.Data.ProfiledDbConnectionFactory(factory);
Database.DefaultConnectionFactory = profiled;
Database.SetInitializer(new ReCouponContextInitializer());
}
The profiler works great except that I can't get it to profile SQL. I am using SQL Server 2008 Express. I've been following the related issues on the Google Code project homepage and am totally stuck.
This one had me stumped for a long time too. It appears that the connection string naming convention takes precedence over Database.DefaultConnectionFactory.
Could you try renaming the connection string in the web.config?
from
<connectionStrings>
<add name="ReCouponContext" connectionString="..." />
</connectionStrings>
to
<connectionStrings>
<add name="ReCoupon" connectionString="..." />
</connectionStrings>
and then change
var factory = new SqlConnectionFactory(ConfigurationManager.ConnectionStrings["ReCouponContext"].ConnectionString);
to
var factory = new SqlConnectionFactory(ConfigurationManager.ConnectionStrings["ReCoupon"].ConnectionString);