Web API 2 EnableCors not working when I post data with DHC Chrome extension - asp.net

I am developing a Web API 2 project and I using EnableCors attribute like this:
Controller:
[EnableCors(origins: "http://localhost:32454, http://localhost:25234", headers: "*", methods: "POST")]
WebApiConfig:
config.EnableCors();
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>
</system.webServer>
When I am posting data to my Web API via DHC Chrome extension, my controller is working fine. But, I set two origin. I don't want to access my Web API via DHC. Because, I didn't allow it.
What should I do?

I usually use Owin with Web Api and this should resolve:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
WebApiConfig.Register(config);
ConfigureOAuth(app);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
}

Related

Map to wwwroot in ASP.Net 4?

Is there an easy way to add a subdirectory in ASP.Net v4 Web API that would contain all of my client content? I have read a lot of articles today on virtual paths and routing, but nothing that quite describes this case.
For example, I want to store my images under wwwroot so when the the app receives this request:
http://myapp/img/logo.png
It fetches wwwroot\img\logo.png to handle the request. Obviously, I don't want to have to map out every file or folder individually.
There will be a Web API restful web service that will be handled by the regular routing functionality in WebApiConfig.cs.
(Note: I ask this because I plan to migrate our app to ASP.Net v5 when it is GA, and this would make moving the client-side code trivial)
You can use the Microsoft.Owin.FileSystem and Microsoft.Owin.StaticFiles NuGet Packages to achive what you want.
First add the two NuGet Packages.
Then add this Code to your Startup class:
public void Configuration(IAppBuilder app)
{
// here your other startup code like app.UseWebApi(config); etc.
ConfigureStaticFiles(app);
}
private void ConfigureStaticFiles(IAppBuilder app)
{
string root = AppDomain.CurrentDomain.BaseDirectory;
string wwwroot = Path.Combine(root, "wwwroot");
var fileServerOptions = new FileServerOptions()
{
EnableDefaultFiles = true,
EnableDirectoryBrowsing = false,
RequestPath = new PathString(string.Empty),
FileSystem = new PhysicalFileSystem(wwwroot)
};
fileServerOptions.StaticFileOptions.ServeUnknownFileTypes = true;
app.UseFileServer(fileServerOptions);
}
Also you have to make sure the handler is registered in your Web.config file. It should look like this:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="FormsAuthentication" />
</modules>
<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" />
<add name="Owin" verb="" path="*" type="Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb"/>
</handlers>
</system.webServer>
Then every file in your "wwwroot" Folder will be automatically accessible.
For example your wwwroot/img/logo.png file will be accessible via http://yourdomain.com/img/logo.png, just like you want it :)
If you generate the content of the wwwroot folder with npm/gulp/grunt in a build event, then maybe you also have to edit your csproj file and add this ItemGroup:
<ItemGroup>
<Content Include="wwwroot\**\*" />
</ItemGroup>
Add img folder to the root directory of your application. Also you have to to include images in the project or application
For handling file routing I would:
Create HttpHandler as workaround for Image handling/or some other static files.
Bundle config for configuring js and css file path.
Create HttpHandler for handling request to specific file extensions.
And modify the file real path using provided file relative path from the URL.
HttpHandler for .jpg files:
public class ServiceSettings
{
public static string RootStaticFolder = "\\wwwroot";
}
public class ImageHandler : IHttpHandler
{
public bool IsReusable { get { return false; } }
public void ProcessRequest(HttpContext context)
{
var fileSystemPath = context.Server.MapPath(Path.Combine("~") + ServiceSettings.RootStaticFolder);
var file = Path.Combine(Path.GetDirectoryName(context.Request.FilePath), Path.GetFileName(context.Request.FilePath));
var filePath = string.Concat(fileSystemPath, file);
if(!File.Exists(filePath))
{
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
context.Response.Status = "404 Not Found";
}
context.Response.WriteFile(filePath);
}
}
For making it work you must disable MVC routing for this king of files.
RouteConfig.cs:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Disable routing for */*.jpg files
routes.IgnoreRoute("{*alljpg}", new { alljpg = #".*\.jpg(/.*)?" });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Then you have to add registration for your HttpHandler to web.config:
<system.webServer>
<modules runAllManagedModulesForAllRequests="false">
<remove name="FormsAuthentication" />
</modules>
<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" />
<add name="jpgs" verb="*" path="*.jpg" type="WebApplication1.ImageHandler" preCondition="managedHandler"/>
</handlers>
</system.webServer>
Also pay attention to runAllManagedModulesForAllRequests="false" setting in modules tag.
Bundle configuration for css/js files
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/wwwroot/Scripts/jquery-{version}.js"));
// Use the development version of Modernizr to develop with and learn from. Then, when you're
// ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
"~/wwwroot/Scripts/modernizr-*"));
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
"~/wwwroot/Scripts/bootstrap.js",
"~/wwwroot/Scripts/respond.js"));
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/wwwroot/Content/bootstrap.css",
"~/wwwroot/Content/site.css"));
}
With this approach it would be very easy during migration to asp.net 5.
You will only need to remove HttpHandler and bundle configurations.

ASP.NET MVC5 with existing Membership database

I have an existing ASP.NET Membership database which I have to stick to. I'm developing a new MVC5 website in VS2013 (update 4) using a new MVC website project template. I have modified web.config to ensure the old Membership type of authentication is specified. I have also modified generated [HttpPost]Login action to ensure I login against my Membership database - it logs me in correctly and generates an authentication cookie as required.
However the website still redirects me to the Login page as I'm not authenticated. The Request.IsAuthenticated does show that I'm not authenticated. What am I missing? What are my options?
EDIT:
web.config changes (only changes):
<connectionStrings>
<add name="MyCS" connectionString="Data Source=sql1;Initial Catalog=MyDB;Persist Security Info=True;User ID=mysa;Password=mypw" providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<authentication mode="Forms">
<forms timeout="20" name="seAdmin" loginUrl="~/Account/Login" />
</authentication>
<roleManager enabled="true" defaultProvider="CustomizedRoleProvider">
<providers>
<clear />
<add name="CustomizedRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="MyCS" applicationName="/seAdmin" />
</providers>
</roleManager>
<membership defaultProvider="CustomizedMembershipProvider">
<providers>
<clear />
<add name="CustomizedMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="MyCS" applicationName="/seAdmin" />
</providers>
</membership>
<machineKey validationKey="63A7C07B191BA3EF02DD4866C420DCAB81C9FFCCC617DE40ED6E2B89A2FC2BA3FA32C39D183FE0708E9279C14E58318D0C5E171C0AF802F154430679D1778485" decryptionKey="F5B9049DECB8C9A23B1D131E63D2ED5C15FF0AEB3C3E96FC" validation="SHA1" />
</system.web>
Login action:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
if (Membership.ValidateUser(model.Email, model.Password))
{
FormsAuthentication.SetAuthCookie(model.Email, model.RememberMe);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1)
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
return View(model);
}
FilterConfig adds a global authorisation attribute
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new AuthorizeAttribute() { Roles = "CWA" });
}
}
I have some theories as to why it doesn't work, firstly in web.config there is a <system.webServer> tag, there must be a line for removing FormsAuthentication, try commenting it out, or add one again, like so:
<system.webServer>
<modules>
<remove name="FormsAuthentication" />
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
</modules>
secondly try User.Identity.IsAuthenticated to see it is false too, also are you have any role in your app?

How to add extension .html in url asp.net mvc 4?

I have the url:
http://localhost:1714/Message/Index
I want to show:
http://localhost:1714/Message/Index.html
How can I do it?
You need to modify Web.config to map requests for your HTML files to TransferRequestHandler.
like so:
<system.webServer>
...
<handlers>
<add name="HtmlFileHandler" path="*.html" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
...
</system.webServer>
This is explained here by Jon Galloway.
And put this to your RouteConfig:
public static void RegisterRoutes(RouteCollection routes)
{
...
routes.MapRoute("Default", "{controller}/{action}.html", new { controller = "Home", action = "Index" });
...
}
Than accessing http://localhost:{port}/Home/Index.html will send you to your Home page.

IIS 7 cannot route requests: error 404, file not found

I've created my first owin/web.api REST service.
Something super simple just to test some features.
I've created an empty project with Visual Studio 2013 and installed a these packages:
Microsoft.AspNet.WebApi.Client
Microsoft.AspNet.WebApi.Core
Microsoft.AspNet.WebApi.Owin
Microsoft.Owin
Microsoft.Owin.Diagnostics
Microsoft.Owin.Host.SystemWeb
Newtonsoft.Json
Owin
This is my startup class:
[assembly: OwinStartup(typeof(OwinO.Startup))]
namespace OwinO
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
app.UseWebApi(config);
app.UseWelcomePage("/");
app.UseErrorPage();
}
}
}
and this is my Api Controller:
[RoutePrefix("api/v1")]
public class TestController : ApiController
{
[HttpGet]
[Route("test")]
public async Task<IHttpActionResult> Get()
{
string name = "Mister";
string sayHello = string.Empty;
Task<string> t = new Task<string>(() =>
{
sayHello = string.Format("Hello {0}", name);
return sayHello;
});
t.Start();
await t;
return Ok(new string[] { sayHello });
}
}
My Web.Config:
<system.web>
<compilation debug="true" targetFramework="4.5.1" />
<httpRuntime targetFramework="4.5.1" />
</system.web>
<system.webServer>
<!--<modules runAllManagedModulesForAllRequests="true" />-->
<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>
</system.webServer>
Nothing really too complicated.
PROBLEM:
This Web.Api service works everywhere.
I've tested it on my PC with IIS Express (8.0) and my IIS 7.5 (Windows 7).
I've deployed it to my hosting provider (Arvixe) and it works.
I've deployed it on a server (Windows 2008 Server R2) and it works.
The problem it does not work where it should work.
My client's server is Windows 2008 sp2 (32 bit) with IIS 7.
I've managed to startup Owin but requests cannot be routed.
I cannot access the address: [server ip]/api/v1/test
WHAT I'VE TRIED:
I've checked the server's configuration:
Framework 4.5.1 is installed.
IIS is up and running (I've got other ASP.NET MVC web apps installed)
I've tried to remove the custom routing prefix:
[RoutePrefix("api/v1")]
I've checked the IIS log and the requests reach IIS.
It's just it does not know how to route.
To cross-check the problem I've created a simple web.api without Owin (with the same routing system) and it works.
The same Owin app self-hosted works.
There is not fix for this.
I've spent a good amount of time trying to find a solution or a way to fix it.
After the server upgrade everything worked as expected.

Why don't trace listeners log custom handler traffic?

I have a custom handler like this,
public class Handler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Write("Hello World");
}
public bool IsReusable
{
get
{
return false;
}
}
}
Why does this not work?
<system.diagnostics>
<sources>
<source name="System.Web" switchValue="All" propagateActivity="true">
<listeners>
<add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="c:\logs\Traces_Documents.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
When that is in the web.config it does nothing when I call the handler. No logging etc.
I have previously used the same trace listener on the System.ServiceModel namespace with a WCF service, and that worked.
Do you have tracing enabled?
<system.web>
<trace enabled="true" writeToDiagnosticsTrace="true" />
</system.web>
Also, what version of the framework / IIS are you using?
See the DnrTV episode w/ Steve Smith which has good information on Asp.Net Tracing.

Resources