Web api routing in subfolder application - c#

I have a main site running under example.com. Now I'm creating a application into example.com subfolder like example.com/subfolder/subsite/, so I have created a application in the subsite folder and everything is working fine, except the routes.
I have the following route:
RouteTable.Routes.MapHttpRoute("myapi", "api/{controller}/{hash}", defaults: new { hash = RouteParameter.Optional });
The route is working fine if I'm debuging the API in localhost or hosting it somewhere else in the root, but it's not working when running inside the subsite application folder.
Any tips?

Did you really create a new web application instead of just a virtual sub directory?
I just tested it, create a simple api controller which returns a string and create a /test site in a /test/sub site, both running the same web api project.
And it simply works.
If this is not the issue, please provide more details... error msg etc...

Related

API Calls to controller is breaking after deploying to IIS

I am invoking API calls to get JSON data from server using javascript.
$(function () {
var customersTable = $('#Customers');
var returnCustomersTable = UpdateDataTable(customersTable, "/Customers/Loaddata");
}
This works fine when I am working with Visual studio Dev environment , because my web application is on root and so all javascripts Works fine.
Example:
My WebSite URL: http://localhost:4391
API Calls will be: http://localhost:4391/Customers/Loaddata
This works fine.
But when I deploy application to IIS, my website URL will be,
My WebSite URL: http://localhost/MyAppName
But API calls would still be,
API Calls will be: http://localhost/Customers/Loaddata, which results in not found.
Since I am using javascript in a separate file , I wont be able to do URL.Action.
The other option would be to create a base URL for dev and prod and the append with each servcie call.
But I am thinking if there is any other way.
The routing configuration in ASP.NET MVC is designed to serve as the single place in the application where all of the URLs can be maintained.
It helps considerably with maintenance of the project if all URLs are generated using routing through one of the UrlHelper based methods, such as Url.Action() rather than hard coded in controllers and views.
As long as your JavaScript is in an MVC view, you can just resolve Url.Action inline.
$(function () {
var customersTable = $('#Customers');
var returnCustomersTable = UpdateDataTable(customersTable,
'#Url.Action("Loaddata", "Customers")');
}
If the JavaScript is in a separate file outside of MVC, consider passing the URL through a variable or function parameter.
This routing feature also makes it easier to deploy ASP.NET MVC, because the generated URLs will adapt to use the application path when the application is not deployed to the root website virtual directory.
Application running in IIS web site root:
/Customers/Loaddata
Application running in virtual subdirectory configured as IIS Application named "MyAppName":
/MyAppName/Customers/Loaddata

Launching a WebApi application from a Windows App

I have a simple WebApi2 app that handles various REST requests. It's essentially a front end for various CRUD operations on an SQL Server Database. Up until now, I've never run it from outside of Visual Studio yet though and I usually don't do Windows specific stuff, but here I am.
My goal is to build this webapp's functionality into a Windows Desktop application (or at least be able to control the webapp from the windows program), mostly so the user can start the Webapp, stop it, see who is connecting to it, etc, but I've got no idea how to go about connecting this particular set of dots. It's actually a pretty tough thing to google.
The WebApp part also needs to be told some things at startup (just strings, so if the answer(s) involve executing various system command lines to tell the WebApp to start/stop/etc and I can pass in what I need on a command line somehow, that's fine).
Ultimately, the goal is to hand the user an install program and he doesn't have to know there is a webserver involved unless he really wants to.
So how would I go about accomplishing this part? (If this question is too vague, tell me why and I'll modify it as necessary).
One of the good things about Web API is the ability to be hosted outside of a web server such as IIS. For example you could host it inside your Windows Forms application. Here's an article with detailed instructions on how to achieve this.
You would have a Startup class that will be used for bootstrapping:
public class Startup
{
// This code configures Web API. The Startup class is specified as a type
// parameter in the WebApp.Start method.
public void Configuration(IAppBuilder appBuilder)
{
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseWebApi(config);
}
}
and then its just a matter of starting the listener:
using (WebApp.Start<Startup>("http://localhost:8080"))
{
Console.WriteLine("Web Server is running.");
Console.WriteLine("Press any key to quit.");
Console.ReadLine();
}
This will make available your Web API on port 8080 locally and your application can send HTTP requests to it.
So basically the keywords that you are looking for are: self hosting asp.net web api.

How to add a Web API service to a non-MVC Asp site?

With the help of several online tutorials, like this one, I am still struggling to add a Web API service to an existing Asp site, that is not MVC.
I added to the project a new item of type Web API Controller Class(v2.1), named it something like AbcController.cs, and VS2015 asked me to put it in the App_Code directory. The default code has handlers for Get, Put etc. Sounded to me like I am on the right track.
I added a default route in Global.asax.cs like in the tutorial:
RouteTable.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
This got built after adding a reference to System.Web.Http.Webhost which was not mentioned in the tutorial. Sounded like I was still on the right track.
However, it doesn't work. I run the site in debug and this gives me a 404 Not Found:
http://localhost:54905/api/abc
I tried to run this on the production server with IIS7, of course as a second test web site to not interfere with the version that is in production. However, I ran into the error that the Microsoft.Web.Infrastructure dll could not be found. To fix this, I should install MVC packages, which I don't like for just an experiment.
My questions are:
do I get it right that the URL is in lower case, i.e., not .../api/Abc ?
does this kind of routing work in the debugger?
am I essentially turning the web site into an MVC web site?
is this really the simplest way to add a "REST" service to an existing web site? I only need to implement the POST, read and return some JSON data, and do not need arguments in the URL

How to publish assets using web-api

I am using a MVC Web Api server application for generating client data. In addition, I want to publish a collection of JavaScript, XAP (Silverlight) and XML files to my client-side application. Currently, I have a project structure in which those directories are mixed through my .Net implementation code (what I do not like), as the client app uses URIs to request these files can not be changed. Nevertheless, I want to separate the client data from the server application implementation in a different folder.
Therefore, is there a way to store the client data in a separate folder, e.g.
/clientdata/JavaScript
/clientdata/XAP
/clientdata/XML
/clientdata/...
in my project, while still being able to access these files using URIs like
/JavaScript
/XAP/
/XML/
Which are the URLs used by the client app and again can not be easily changed.
This is the main method of my Global.asax
AreaRegistration.RegisterAllAreas();
RouteTable.Routes.MapRoute(
name: "Default",
url: string.Empty,
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "TCMsimulator.Controllers" }
);
var config = new Microsoft.ApplicationServer.Http.HttpConfiguration();
RouteTable.Routes.MapServiceRoute<ResourcesService>("resources/", config);
RouteTable.Routes.MapServiceRoute<PublicResourcesService>("publicresources/",config);
RouteTable.Routes.MapServiceRoute<MonitorService>("monitor/", config);
Is there a way to add a folder redirect to the routing table, such that a virtual folder in the URI is redirected to a filesystem folder? Like can be done using ModRewrite in Apache? It seems like a simple problem, but I have not found a solution to it in Web Api.
Thanks in advance!
I recommend using Attribute Routing. It is much more understandable. You can see examples of multiple routes mapped to a single resource.
http://attributerouting.net/
If these directories only contain files and not Web Api generated output, you should probably ignore the routes to the directories and make sure the requests for them run outside of Web Api, like regular static files that are served from IIS (e.g. images).

Fresh Windows + VS2012 = MVC3 Problems

I just recently got a fresh install of Windows 7 on a my PC running VS2012/VS2010. I have an MVC3 project that ran just fine before I pulled it onto this PC to run. The project still compiles on this PC and I can navigate through my site while running the app in studio (2010 or 2012), but when I tried to POST from ANY form in ANY view and pass an ID by means of the URL like this:
<form id="ScriptForm" action="/MyApp/ControllerName/ActionName/#ViewBag.IDNumber" method="post">
...
</form>
...I got this error. I did some digging and playing around to try to fix this, ultimately taking these steps to try to resolve:
Actually installed ASP.NET via the Windows Components form in Control Panel
Changed the application to use IIS Express
Well, when I changed it to run under IIS Express, I started getting a different error.
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is
temporarily unavailable.
Most likely causes:
The directory or file specified does not exist on the Web server.
The URL contains a typographical error.
A custom filter or module, such as URLScan, restricts access to the file.
Things you can try:
Create the content on the Web server.
Review the browser URL.
Check the failed request tracing log and see which module is calling SetStatus. For more information, click here.
Detailed Error Information:
Module IIS Web Core
Notification MapRequestHandler
Handler StaticFile
Error Code 0x80070002
Requested URL http://localhost:51596/MyApp/ControllerName/ActionName/1
Physical Path C:\CODE\MyApp\ControllerName\ActionName\1
Logon Method Anonymous
Logon User Anonymous
Request Tracing Directory C:\Users\cbarlow\Documents\IISExpress\TraceLogFiles\MYAPP
More Information:
This error means that the file or directory does not exist on the server. Create the file or directory and try the request again.
View more information ยป
It's almost as if it is not recognizing that this is a route and is trying to resolve the URL to a physical file (like 1.html) which obviously does not exist. But why isn't it "doing the MVC thing" and using the route? I have this in my global.asax:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
And I know this is running because I can breakpoint it.
Specs:
Windows 7 | Visual Studio 2010/2012 | Microsoft MVC3 | IIS Express
I've read all these SO posts, none seem to apply in this situation or do not help (mostly, because they apply to actual aspx pages, where I am trying to load pages via controllers):
The HTTP verb POST used to access path '/' is not allowed
The HTTP verb POST used to access path is not allowed
The HTTP verb POST used to access path '/Membership/user/' is not allowed
The HTTP verb POST used to access path '/Main/[object Object]' is not allowed
The HTTP verb POST used to access path '[my path]' is not allowed
HTTP verb POST used to access path '/' is not allowed in Facebook app
Any ideas?
The problem is here (due to my lack of experience with MVC/CSHTML):
<form id="ScriptForm" action="/MyApp/ControllerName/ActionName/#ViewBag.IDNumber" method="post">
...
</form>
The MyApp used to work on my PC (I'm honestly not sure why it doesn't work now... maybe I had set something up for that name to resolve before?) but it no longer maps to anything. It DOES work on the server, but that's because there is indeed a mapping for "MyApp" in IIS. Simply changing this form to this:
<form id="ScriptForm" action="#Url.Content("~/ControllerName/ActionName/" + ViewBag.IDNumber)" method="post">
...
</form>
...does the job more elegantly and without errors.

Categories