Web api routing only permits one controller - web

I created a new Web API project and created the following routing spec (actually I have simplified, looking for the bug):
// Web API configuration and services
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}"
);
When I make a call via ajax with the route:
/api/account/GetSUID/0
everything works fine. When I just use a different controller:
/api/tile/GetTileSet/0
it returns a status of 200 but instead of hitting my controller, it just returns the contents of the default page in jqXHR.responseText! It is as if it is just skipping any API routing like I am requesting the default site page.
I am baffled by this one as I have written literally hundreds of web API functions over the past few years in several other projects. I have never had any issue making calls to multiple controllers. I have looked high and low for what could be happening here and am hoping that someone here might have an idea.
Here is a sample method on the controller:
[HttpGet]
public HttpResponseMessage CheckRequestedID(int id, [FromUri]string Search)
{
if (!BSDIUtil.HasAllAcceptableCharacters(Search))
return Request.CreateResponse(HttpStatusCode.BadRequest);
if (FolderModel.IDAlreadyExists(DAL, Search)) // We can check this because this function is only called when staff members are creating accounts for other people (participants always use their email).
return Request.CreateResponse(HttpStatusCode.OK, false);
else
return Request.CreateResponse(HttpStatusCode.OK, true);
}
This will work if on the account controller but not on the tile controller.
One other thing, I am using the "Community" edition of Visual Studio and Windows 8.1

This is not a problem that is likely to occur often but I have solved it and figured I would post it here in case anyone else has the same issue.
I am using web api in the context of a standard web forms app (although I am only using webforms for my reporting pages). In the web.config for a web forms app, you can declare the paths that the user has access to before authenticating. I was only providing access to the account controller: all others were not permitted due to my authentication mechanism. Once I authenticate (e.g. the forms authentication call) or if I change the location path to include only "api", the problem goes away.

I was facing same problem but in different context. Had many controllers and respective routing templates. Only one controller was responding to requests.
Later i realized my other controller classes were not public!!

Related

pass through 2 Basic Authentication levels for the same URL using request module

I have a web service that uses request module nodejs to get into another service in php protected by basic authentication, using below code, everything was working as expected
request.get(url).auth(cred.username, cred.password, false);
we recently implemented another level of basic authentication on the web server level for different purposes, now I have 2 levels of authentication, I tried to duplicate this request command by doing
request.get(url).auth(cred.username01, cred.password01, false);
request.get(url).auth(cred.username02, cred.password02, false);
this did not work, anyone had similar issue before, any help ?
Javascript is Asynchronous, you will need to execute the second get request inside of a callback for the first one.

MVC Web API in SharePoint site

We're moving most of our web presence to our SharePoint server in the cloud. Our current setup uses a MVC Web API for data retrieval from DB. We do not want to host the API under a separate domain and thus need to move the API under SharePoint domain as well. There is no relaxation in this requirement.
Is there a way to publish my API to SharePoint? Or is there a SharePoint specific API project template in Visual Studio? If not what are my options?
EDIT Initially I have asked that MVC API needs to be part of the SharePoint 2013. But now things are such that API can reside anywhere - inside or outside - of SharePoint, as long as it is accessible from the root domain - which so far it seems not allowed (Error message: Calls to WebProxy without an app context are not allowed."). Still trying to see if this is possible, and if yes, how?
It sounds like the proxy you want to create is already part of SharePoint JSOM. Have a look at these:
http://msdn.microsoft.com/en-us/library/office/fp179895(v=office.15).aspx
http://msdn.microsoft.com/en-us/library/office/jj245162(v=office.15).aspx
This will allow you to overcome cross origin issues. The SP.WebProxy and SP.WebRequestInfo allow you to use javascript to make a call outside of the domain where the javascript executes.
What really happens behind the scenes is that SharePoint's javascript API sends the request to your sharepoint.com tenancy server, which will then invoke the service from the SharePoint server, and return the response back to your javascript. You can implement it like so in a sharepoint-hosted app:
// this javascript executes from my-company.sharepoint.com
var responseDocument = undefined;
$('#cross').click(function () {
var ctx = SP.ClientContext.get_current();
var request = new SP.WebRequestInfo();
request.set_url('https://www.somewebapi.com/my/custom/route');
request.set_method("GET");
responseDocument = SP.WebProxy.invoke(ctx, request); // executes on sp server
ctx.executeQueryAsync(onSuccess, onError);
});
function onSuccess() {
var response = responseDocument.get_body();
alert('success ' + response);
}
function onError(err) {
alert(JSON.stringify(err));
}
...and since the remote api hosted at the other domain is called from the server, you don't have to worry about any of the cross-domain issues.
Update
To answer your update, please check the results from this link.
Have you added the remote endpoint to your AppManifest.xml?
SharePoint doesn't give you a chance to define you own routes. Thats why you can not use old fashioned SharePoint solution to publish asp.net web api. You may consider using apps for SharePoint. It's like separate App with some connections to SharePoint.
Ultimately switched to JSONP solution. Installed the WebApiContrib.Formatting.JsonP in my MVC Web API project in Visual Studio, and modified SharePoint JavaScript, that calls the API, to include ?callback=? (callback is equal to question mark). Everything stays the same. No SharePoint's proxy caller needed! No SharePoint app needed!

Microsoft Unity - How to register connectionstring as a parameter to repository constructor when it can vary by client?

I am relatively new to IoC containers so I apologize in advance for my ignorance.
My application is a asp.net 4.0 MVC app that uses the Entity Framework with a Repository layer on top of that. It is a multi tenant application so the connection string that is used varies by the logged in client.
The connection string is determined by a 'key' that gets passed in as part of the route which indicates the client. This route data is only present on the first request of the user's session.
The route looks kind of like this: http://{host}/login/dev/
where 'dev' indicates we are using the dev database.
Currently the IoC container is registering all dependencies in the global.asax Application_Start event handler and I have the 'key' hardcoded as follows:
var cnString = CommonServices.GetDBConnection("dev");
container.RegisterType<IRequestMgmtRecipientRepository, RequestMgmtRecipientRepository>(
new InjectionConstructor(cnString));
Is there a way with Unity to dynamically register the repository based on the logged in client using the route data that is supplied initially?
Note: I am not manually resolving the repositories. They are getting constructed by the container when the controllers get instantiated.
I am stumped.
Thanks!
Quick assumption, you can use the host to identify your tenant.
the following article has a slightly different approach http://www.agileatwork.com/bolt-on-multi-tenancy-in-asp-net-mvc-with-unity-and-nhibernate-part-ii-commingled-data/, its using NH, but it is usable.
based on the above this hacked code may work (not tried/complied the following, not much of a unity user, more of a windsor person :) )
Container.RegisterType<IRequestMgmtRecipientRepository, RequestMgmtRecipientRepository>(new InjectionFactory(c =>
{
//the following you can get via a static class
//HttpContext.Current.Request.Url.Host, if i remember correctly
var context = c.Resolve<HttpContextBase>();
var host = context.Request.Headers["Host"] ?? context.Request.Url.Host;
var connStr = CommonServices.GetDBConnection("dev_" + host); //assumed
return new RequestMgmtRecipientRepository(connStr);
}));
Scenario 2 (i do not think this was the case)
if the client identifies the Tenant (not the host, ie http: //host1), this suggests you would already need access to a database to access the client information? in this case the database which holds client information, will also need to have enough information to identify the tenant.
the issue with senario 2 will arise around anon uses, which tenant is being accessed.
assuming senario 2, then the InjectionFactory should still work.
hope this helps

This controller won't show up in Web Api on Azure

namespace StorageRoleMVC4.Controllers
{
public class SearchController : ApiController
{
public Dictionary<string, string> Get([FromUri] string searchString, [FromUri] string searchObject)
{
var searchHelper = new SearchStorageHelper();
var objectList = searchHelper.Retrieve(searchString, searchObject);
return objectList;
}
}
}
Is there anything about this controller that makes it unreachable once it's deployed (to an Azure web role)? I just get a 404 error when I try to reach it. It works great on the local emulator.
The last 2 times I've deployed my project, all the controllers in my web service have returned 404 errors for several hours, until the project seems to fix itself. I'm not sure why, but it might be related.
UPDATE
There is a WARNING in the event log on the web role VM after I publish:
The application '/' belonging to site '1273337584' has an invalid AppPoolId 'ea7a2e15-9390-49e1-a16b-67ff1cdb7dcb' set. Therefore, the application will be ignored.
This is the id of my site, but the AppPoolId is not correct. Changing the app pool turns the 404 into a 502.
Also, after publishing, the World Wide Web Publishing Service is turned off. When I turn it on and do an IIS reset, after the reset it's turned off again.
When I reboot the web role VM, most of the controllers work again, and the World Wide Web Publishing Service is turned on. But still, this SearchController doesn't work. Or any other new controllers I've created since this problem started happening.
Well, after a ridiculous amount of unsuccessful troubleshooting, I just rolled back to an earlier version of the code and found that it didn't read the web service when I deployed it. So I started over with that version and re-built the delta.
This involved removing a few web.config entries and removing some libraries, creating a few classes and referencing them in the global.asax (I think that's where it was) in order to override te Authorize attribute...
If anyone has a better answer, I will switch the answer to what you post.

Render mobile version of login in Secure class Play! Framework

Is it possible to somehow override the login method of the Secure.java class of the Secure-Module in Play! Framework, so that another version of the login form is displayed?
In my case, i want to display a mobile version of the login-form if a mobile browser is detected.
I know i should not change the Secure.java class itself, but i don't really see any other solution to this problem.
As discussed in other posts you have the request in your Play! controller. So in this request you could ask which agent is trying to view your website:
String agentInfo = request.headers.get("user-agent");
The you can determine which template will be rendered for this agent:
if (agentType.isWhatEverHeIs) {
renderTemplate("Application\mobileTemplateForBadPractise.html");
} else {
render();
}
But what I would encourage you to do is responsive webdevelopment. Create your templates as smart as possible, let the template and css and javascript do this and keep your business logic in your controller.
You could use the Twitter Bootstrap to achieve this, but there are many more! Like Skeleton.
You even got the request object inside your templates so that you can optionally render things in your template (or not) based on the agent.
Even simpler, simply create/override the secure/login.html template and use responsive design : media queries. No need to change the controller or check agent or whatever.

Resources