angular 2 with spring-boot security rest api - angularjs

I am developing a webapp that has frontend written in Angular2 (typescript) which generate from angular cli and Spring Boot 1.5.2 RELEASE. As I've wanted to work decoupled I have my REST deployed on Tomcat(localhost:8084 with contextpath app-api) and the frontend on angular cli (localhost:4200).
My problem when I login and then call other api, but result is 401. JSessionId is not keep and send in header of the second request after logining success.
This is my bean config:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<global-method-security />
<beans:bean id="failureHandler" class="my.app.auth.RESTAuthenticationFailureHandler"></beans:bean>
<beans:bean id="successHandler" class="my.app.auth.RESTAuthenticationSuccessHandler"></beans:bean>
<beans:bean id="loginUrlAuthenticationEntryPoint" class="my.app.auth.RESTAuthenticationEntryPoint"></beans:bean>
<beans:bean id="loginPathRequestMatcher" class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
<beans:constructor-arg type="java.lang.String" value="/login" />
</beans:bean>
<beans:bean id="customUsernamePasswordAuthenticationFilter"
class="my.app.auth.AuthenticationFilter">
<beans:constructor-arg ref="loginPathRequestMatcher"/>
<beans:constructor-arg ref="environment"/>
<beans:constructor-arg ref="httpClient"/>
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="sessionAuthenticationStrategy" ref="session-management" />
<beans:property name="authenticationFailureHandler" ref="failureHandler" />
<beans:property name="authenticationSuccessHandler" ref="successHandler" />
</beans:bean>
<http auto-config="false" use-expressions="true"
disable-url-rewriting="true" entry-point-ref="loginUrlAuthenticationEntryPoint">
<csrf disabled="true" />
<custom-filter position="FORM_LOGIN_FILTER"
ref="customUsernamePasswordAuthenticationFilter" />
<custom-filter after="FORM_LOGIN_FILTER" ref="concurrencyFilter" />
<intercept-url pattern="/login" access="permitAll" />
<intercept-url pattern="/" access="permitAll" />
<intercept-url pattern="/api/**" access="hasAnyRole('ROLE_USER')" />
<logout logout-success-url="/login" />
<headers>
<frame-options policy="SAMEORIGIN" />
<hsts include-subdomains="true" disabled="false" />
<header name="Access-Control-Allow-Origin" value="*"/>
<header name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS, DELETE"/>
<header name="Access-Control-Max-Age" value="3600"/>
<header name="Access-Control-Allow-Headers" value="x-requested-with, authorization, Content-Type, *"/>
</headers>
<session-management
session-authentication-strategy-ref="session-management" />
</http>
<beans:bean id="concurrencyFilter"
class="my.app.auth.ConcurrentSessionFilter">
<beans:constructor-arg ref="sessionRegistry" />
<beans:constructor-arg name="expiredUrl" value="/" />
</beans:bean>
<beans:bean id="sessionRegistry" class="my.app.auth.SessionRegistry" />
<beans:bean id="session-management"
class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
<beans:constructor-arg>
<beans:list>
<beans:bean
class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
<beans:constructor-arg ref="sessionRegistry" />
</beans:bean>
<beans:bean
class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy" />
<beans:bean
class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
<beans:constructor-arg ref="sessionRegistry" />
</beans:bean>
</beans:list>
</beans:constructor-arg>
</beans:bean>
<authentication-manager alias="authenticationManager">
<authentication-provider ref="customAuthenticationProvider" />
</authentication-manager>
<beans:bean id="customAuthenticationProvider" class="my.app.auth.UserAuthProvider" />
<beans:bean id="authenticationService" class="my.app.auth.AuthenticationService" />
</beans:beans>
I refer angular2-spring-boot-security topic, but I cannot resolve my problem or maybe i not yet understand this solution.
Have any suggestion for my problem? Or discuss with me? Thanks.

Thank all. I solved my problem by declare exactly Access-Control-Allow-Origin. And use withCredentials in config spring, http in angular 2:
<header name="Access-Control-Allow-Origin" value="http://localhost:4200"/>
<header name="withCredentials" value="true"/>
<header name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS, PUT, PATCH, DELETE"/>
<header name="Access-Control-Max-Age" value="3600"/>
<header name="Access-Control-Allow-Headers" value="*"/>
<header name="Access-Control-Allow-Credentials" value="true"/>
And add http config in constructor of component:
constructor(private http: Http) {
let _build = (<any>http)._backend._browserXHR.build;
(<any>http)._backend._browserXHR.build = () => {
let _xhr = _build();
_xhr.withCredentials = true;
return _xhr;
};
}
It's work fine with Get method request. But now i have big problem with Post method request. When I add Content-Type into header, request not import JSESSIONID from cookie, but if i don't add Content-Type i will get error code 415 about error Media Type of server.
I tried with Http of angular 2 and XMLHttpRequest. What's wrong here?

Related

IUP - Windows SDK static link

I want to write a multiplatform, native desktop application in C. After some searching, I found IUP to be the perfect fit. Unfortunately, I'm struggling to link the Windows SDK. For now, I just want to statically compile the x64 version for Windows 8.1. When I compile this example in Code::Blocks, I get the following errors:
g++.exe -LC:\MinGW\iup -o "bin-debug\EVE Editor.exe" obj-debug\main.o -lgdi32 -luser32 -lkernel32 -lcomctl32 -lole32 -lfreetype6 -liup -liup_mglplot -liup_plot -liup_scintilla -liupcd -liupcontrols -liupgl -liupglcontrols -liupim -liupimglib -liupmatrixex -liupole -liuptuio -lz
C:\MinGW\iup/libiup.a(iupwin_font.o):iupwin_font.c:(.text+0x1db): undefined reference to `__imp_CreateFontW'
C:\MinGW\iup/libiup.a(iupwin_font.o):iupwin_font.c:(.text+0x224): undefined reference to `__imp_SelectObject'
C:\MinGW\iup/libiup.a(iupwin_font.o):iupwin_font.c:(.text+0x240): undefined reference to `__imp_GetTextMetricsW'
C:\MinGW\iup/libiup.a(iupwin_font.o):iupwin_font.c:(.text+0x684): undefined reference to `__imp_SelectObject'
C:\MinGW\iup/libiup.a(iupwin_font.o):iupwin_font.c:(.text+0x734): undefined reference to `__imp_GetTextExtentPoint32W'
And so on and so forth. Here the IUP documentation says "For Windows, if you statically link the application with IUP you must link also with the libraries ole32.lib and comctl32.lib (provided with the compilers)." So I obtained the Windows SDK from here and recompiled with ole32 and comctl32. I got the same errors. I also looked at the Code::Blocks guide on the same page, but it's for dynamic linking.
I've never linked the Windows SDK before so I'm at a loss. Here is my Code::Blocks project:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="EVE Editor" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin-debug/EVE Editor" prefix_auto="1" extension_auto="1" />
<Option object_output="obj-debug/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-g" />
</Compiler>
</Target>
<Target title="Release">
<Option output="bin/EVE Editor" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/" />
<Option type="0" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O2" />
</Compiler>
<Linker>
<Add option="-s" />
</Linker>
</Target>
</Build>
<Compiler>
<Add option="-Wall" />
<Add directory="C:/MinGW/iup/include" />
</Compiler>
<ResourceCompiler>
<Add directory="C:/MinGW/iup/etc" />
</ResourceCompiler>
<Linker>
<Add library="gdi32" />
<Add library="user32" />
<Add library="kernel32" />
<Add library="comctl32" />
<Add library="ole32" />
<Add library="libfreetype6.a" />
<Add library="libiup.a" />
<Add library="libiup_mglplot.a" />
<Add library="libiup_plot.a" />
<Add library="libiup_scintilla.a" />
<Add library="libiupcd.a" />
<Add library="libiupcontrols.a" />
<Add library="libiupgl.a" />
<Add library="libiupglcontrols.a" />
<Add library="libiupim.a" />
<Add library="libiupimglib.a" />
<Add library="libiupmatrixex.a" />
<Add library="libiupole.a" />
<Add library="libiuptuio.a" />
<Add library="libz.a" />
<Add directory="C:/MinGW/iup" />
</Linker>
<Unit filename="main.c">
<Option compilerVar="CC" />
</Unit>
<Extensions>
<code_completion />
<envvars />
<debugger />
<lib_finder disable_auto="1" />
</Extensions>
</Project>
</CodeBlocks_project_file>
Try changing the order the linking is done. The dependency order must be reversed, I mean least dependent libraries last. For instance:
<Add library="libiupcontrols.a" /> -- optional
<Add library="libiupcd.a" /> -- optional
<Add library="libcd.a" /> -- optional
<Add library="libfreetype6.a" /> -- optional
<Add library="libz.a" /> -- optional
<Add library="libiup.a" />
<Add library="gdi32" />
<Add library="user32" />
<Add library="kernel32" />
<Add library="comctl32" />
<Add library="ole32" />
And you don't need to include all the IUP libraries, just the ones you actually use.

Cors not working in web api2 project

Hi I am developing web api2 project. I hosted application in server 192.168.0.213 and I am trying to access the methods as below.
this.getSubs = function () {
var url = 'http://192.168.0.213:7777/api/User_Creation/';
return $http.get(url).then(function (response) {
return response.data;
});
}
Above function returns the data with no issues.
For example my below methods with verbs such as PUT,DELETE and POST not working.
this.saveSubscriber = function (sub) {
return $http({
method: 'post',
data: JSON.stringify(sub),
url: 'http://192.168.0.213:7777/api/User_Creation/',
contentType: "application/json"
});
}
I tried many ways still did not worked any methods. Currently i have below code in web.config file.
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="POST,GET,PUT,DELETE" />
</customHeaders>
Also i have below line of code in webapiconfig.cs file.
private static void EnableCrossSiteRequests(HttpConfiguration config)
{
var cors = new EnableCorsAttribute(
origins: "*",
headers: "*",
methods: "*");
config.EnableCors(cors);
}
Also i have below line of code in controller. Still does not working anything.
[EnableCors(origins: "http://192.168.0.213:7777", headers: "*", methods: "*")]
Also i commented . I tried all the ways only GET verb is working fine. My insert update delete operations are not working. May I know where i am doing things wrong? May i get some help on this as i tried my best still no luck.. Thank you all.
try wigh something like this: (for me work perfectly):
Startup.cs file: (install Microsoft.Owin.Cors nuget packages before)
using Goocity.API;
using Microsoft.Owin;
using Microsoft.Owin.Cors;
using Owin;
[assembly: OwinStartup("API", typeof(Goocity.API.Startup))]
namespace Goocity.API
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
#region TO UNCOMMENT WHEN IS IN PRODUCTION
//var corsPolicy = new CorsPolicy
//{
// AllowAnyMethod = true,
// AllowAnyHeader = true,
// SupportsCredentials = true,
// Origins = { "http://www.mysite.it" }
//};
//app.UseCors(new CorsOptions
//{
// PolicyProvider = new CorsPolicyProvider
// {
// PolicyResolver = context => Task.FromResult(corsPolicy)
// }
//});
#endregion TO UNCOMMENT WHEN IS IN PRODUCTION
app.UseCors(CorsOptions.AllowAll);
ConfigureAuth(app);
}
}
}
then your webconfig: (in the system.webserver section)
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Credentials" value="true" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept, X-Token, Cache-Control" />
<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
</customHeaders>
</httpProtocol>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
<remove name="FormsAuthentication" />
</modules>
<staticContent>
<remove fileExtension=".woff" />
<mimeMap fileExtension=".woff" mimeType="application/font-woff" />
<remove fileExtension=".woff2" />
<mimeMap fileExtension=".woff2" mimeType="application/font-woff2" />
<remove fileExtension=".json" />
<mimeMap fileExtension=".json" mimeType="application/json" />
</staticContent>
<!--<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
</rule>
</rules>
</rewrite>-->
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<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" />
</handlers>
</system.webServer>
Hope it help you!!...
You should have [EnableCors(origins: "http://192.168.0.54", headers: "*", methods: "*")] in other words, your EnableCors should specify the client that attempts to connect, not the server itself

Angular post, put, delete returns 405

I am new to angular.
I cant invoke POST, PUT and DELETE methods using angular (GETs working fine)
I have a .NET WebApi server which all methods and all resources URLs works and tested using Advanced Rest Client.
This is the code:
$scope.updateUser = function() {
var url = 'http://localhost/api/users/' + $scope.selectedId;
$http.put(url, $scope.user,{'content-type' : 'application/json'})
.then(
function(response) {
alert("1");
},
function(errResponse) {
alert("2");
}
);
};
I tried with 'content-type':'application/x-www-form-urlencoded', I tried with no config at all, I tried the one with success and error and I tried the one whith command and data attributes.
I get nothing back and while debugging, errResponse contains only the request data. Checked the network tab in the developer tools, and I found that 405 returned.
Again, all URLs are valid and tested using a third party REST client app.
Can any one help?
EDIT:
web.config:
<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>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
</modules>
<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>
PUT example:
[HttpPut]
[Route("api/users/{id}")]
public IHttpActionResult updateUser(int id, User user)
Regards,
Ido
adding this snippet to web.config should resolve problem :
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
</modules>
</system.webServer>

The requested resource does not support http method 'OPTIONS'.?

I am making the following request to an asp.net web api PUT method from my angular.js client:
var org = {
OrgId: 111,
name: 'testing testing'
};
$http.put("http://localhost:54822/api/data/putorganisation/1/", org).then(function(status) {
console.log("success PUT");
return status.data;
});
However getting the following errormsg (in fiddler):
{"message":"The requested resource does not support http method 'OPTIONS'."}
This is a part of my asp.net web api web.config file:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type,x-xsrf-token,X-Requested-With" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
<validation validateIntegratedModeConfiguration="false" />
<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" />
<remove name="WebDAV" />
</handlers>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
</modules>
</system.webServer>
data controller web api:
public HttpResponseMessage Options()
{
var response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.OK;
return response;
}
public HttpResponseMessage PutOrganisation(int id, [FromBody]Organisation org)
{
var opStatus = _Repository.UpdateOrganisation(org);
if (opStatus.Status)
{
return Request.CreateResponse<Organisation>(HttpStatusCode.Accepted, org);
}
return Request.CreateErrorResponse(HttpStatusCode.NotModified, opStatus.ExceptionMessage);
}
This is my question: Why do I get the errormsg ( see above) when I make exactly the same request in fiddler ( works) as in the angularclient (does not work)??
I know this is an old question, but I ran into the same problem and figured I could help others who are trying to figure out.
I solved it by removing 2 of the handler configurations in the Web.config:
<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>
I don't know exactly why it fixed the problem, but my working theory is that <remove name="OPTIONSVerbHandler" /> makes OPTIONS requests forbidden by default. When sending the request from a browser, it sends an OPTIONS request first before the PUT request, so it never gets to the PUT request because the first OPTIONS request was denied as an invalid http method on the api.
In fiddler, I am assuming that it just sends only the PUT request (I observed the same behavior using the Postman web app sending requests manually). So it skips the forbidden OPTIONS request and succeeds.
I also faced the same issue, after few research, I did following changes to web.config and Global.asax.cs files
<configuration>
<system.webServer>
<directoryBrowse enabled="true" />
<validation validateIntegratedModeConfiguration="false" />
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, PATCH, DELETE, OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
</customHeaders>
</httpProtocol>
<handlers>
<remove name="WebDAV" />
<remove name="OPTIONSVerbHandler"/>
<remove name="TRACEVerbHandler" />
<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="C:\windows\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="C:\windows\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" />
</handlers>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
<remove name="ApplicationInsightsWebTracking" />
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
</modules>
</system.webServer>
</configuration>
Add the following code global.ascx.cs
protected void Application_BeginRequest()
{
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
This is almost certainly a CORS problem. I'd first read up about it to make sure you understand what this is and why it is important. And I would guess that your server configuration is not correct.
Unfortunately, I don't know much about .net, but this CORS tutorial for .net describes what you should do quite clearly.
It looks like you are missing an EnableCors annotation. It looks like you need to add something like [EnableCors("*", "*", "*")] to your controller. Explicit handling of OPTIONS is not necessary. Of course, in producition, you don't want to use wildcards for your CORS handling. They should be more specific, but this is fine for testing.
Andrew is correct, it is most probably a CORS issue. What you need is to add EnableCors attribute to your Controller class so that is looks something like this
[EnableCors(origins: "https://example.com,http://example.org", headers: "*", methods: "*")]
public class TestController : ApiController
{
// your code
The other way to do this is mentioned in this stack overflow post
Yep, an oldie but a goodie. I had the same problem and symptom but my resolution was self-inflicted. I'll share it anyway. The way our service configured the controller used in all of the MapHttpRoute calls at startup included the [DisableCors] attribute. As soon as I reconfigured my local machine startup to use a different controller, everything worked. So if you've done everything else listed here then check your controller and make sure you didn't do something stupid, like I did.
Apparently, in certain cases, an OPTIONS request is sent before the "real" request to determine whether the real request is safe to send due to CORS. See the following MS article at: http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api and search for "Preflight Requests".
Some of the following Q&As might also help:
jQuery $.ajax(), $.post sending "OPTIONS" as REQUEST_METHOD in Firefox
AJAX in Chrome sending OPTIONS instead of GET/POST/PUT/DELETE?
Why does this jQuery AJAX PUT work in Chrome but not FF
How to support HTTP OPTIONS verb in ASP.NET MVC/WebAPI application

Log4net not printing to console in wpf

I have a WPF application with 2 log4net appenders in log4net, the first printing to file and the second should print to console.
For some reason I am not being able to show the result on log4net, but I do see it in the file. What is wrong?
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net debug="true">
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:\\Temp\\1.txt" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="10MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5p %d %5rms %-22.22c{1} %-18.18M - %m%n" />
</layout>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
<layout type="log4net.Layout.PatternLayout">
<param name="Header" value="[Header]\r\n" />
<param name="Footer" value="[Footer]\r\n" />
<param name="ConversionPattern" value="%-5p %d %5rms %-22.22c{1} %-18.18M - %m%n" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="RollingLogFileAppender" />
<appender-ref ref="ConsoleAppender" />
</root>
</log4net>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
Do you see a console pop up when you start the application.
It could be you have to configure your application as a console project to have a console window...
Otherwise you can check trace info. Normally an appender tries to leave one error message there if he can't log to the desired location.
Output window of visual studio catches trace messages when debugging...
Possible duplicate: Log4net won't log to console (WinForms app)
If you are wanting to see the messages in the output window in visual studio you should use the following instead:
<appender name="TraceAppender" type="log4net.Appender.TraceAppender" >
Do you call once XmlConfigurator.Configure() ?

Resources