I'm creating a WebApi in ASP.NET. I want one of my get methods to allow a string to be passed into it. This string will function as a path to a branch in TFS where I'll do a QueryHistory to return its history.
In my WebApiConfig.cs file:
config.Routes.MapHttpRoute(
name: "Branches",
routeTemplate: "api/branches/{fullPath}",
defaults: new { controller = "branches", fullPath = RouteParameter.Optional }
);
In my controller.cs file:
// GET api/branches/$/Project/Branches/Path/To-This-Branch
public string Get(Uri fullPath)
{
string output = "";
NetworkCredential cre = new NetworkCredential("COSMO\\pd-srv", pWord);
TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(new Uri("http://fortknox:8080/tfs/PD"), cre);
var service = tfs.GetService<VersionControlServer>();
string s = System.Uri.UnescapeDataString(fullPath);
var latestChange = service.QueryHistory(s, RecursionType.None, 1);
//output = JsonConvert.SerializeObject(latestChange);
//return a json formatted string containing the full history of the branch path passed in
return "value";
}
I've tried multiple ways, just seems like when I pass in a uriEncoded parameter the UnescapeDataString only accepts strings so it doesn't work. If I pass in the string I get an error due to the '/'.
How can I pass this path from my javascript to my Get() call in my api?
I have run into this as well in the past and solved it by converting "/" to "!" and then converting back in the API. You could substitute any character(s) there... you just need to get rid of the "/"
You can use {*fullPath} in the end of your route template to match the fullPath using a wildcard expression.
config.Routes.MapHttpRoute(
name: "Branches",
routeTemplate: "api/branches/{*fullPath}",
defaults: new { controller = "branches", fullPath = RouteParameter.Optional }
);
See MSDN: Handling a Variable Number of Segments in a URL Pattern
Try call Get method:
api/branches?fullPath="directory1/directory2"
Related
I have created web API that is working fine as i checked that, but the problem is when i call that web API in asp .net website here is a code below of calling web API
protected void btn_search_Click(object sender, EventArgs e)
{
HClient.BaseAddress = new Uri("http://localhost:50653/");
HClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
BoiMember obj = new BoiMember();
obj.CustomerId = txt_customerid.Text.Trim();
obj.AadhaarNo = txt_aadharno.Text.Trim();
obj.CustomerName = txt_name.Text.Trim();
obj.AccountNo = txt_accountno.Text.Trim();
obj.MobileNo = txt_mobile.Text.Trim();
obj.branchcd = Session["BranchCode"].ToString();
obj.ZoneCode = Session["ZoneCode"].ToString();
obj.Campcd = "1";
obj.ind = 1;
obj.SourceType = 2;
obj.UserId = Session["UserName"].ToString();
string uri = "api/BoiMember/GetRecord/";
var response = HClient.GetAsync(uri+obj).Result;
if (response.IsSuccessStatusCode)
{
var GetData = response.Content.ReadAsAsync<IEnumerable<BoiMember>>().Result;
GvdRecords.DataSource = GetData;
GvdRecords.DataBind();
}
else
{
}
}
Where in the API controller named BoiMemberController when I call this web API without parameters it works fine but as I Pass parameters I get the status code 404 Error not found. My web APIConfig.cs has a code
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
By default when you do [some object].ToString() the ToString method returns the objects type. So you are probably passing a string similar to api/BoiMember/GetRecord/BoiMember (not sure on the fully qualified type). You need to build up the uri using string formatting. Here is a basic example with 2 parameters:
var uri = string.Format("api/BoiMember/GetRecord/?customerId={0}&aadhaarNo={1}"
, txt_customerid.Text.Trim()
, txt_aadharno.Text.Trim());
This assumes that your parameters are query string parameters. If you have a web api with the parameter positioned inside the url then you need to change the structure of the string accordingly.
You should also have null checks if necessary and also if a parameter if empty you might not want to send it to the api.
I'm trying to programmatically map a query string to an SEO friendly route URL I've created within my RouteConfig.cs file but appear to be having difficultly.
My route configuration looks like this:
routes.MapRoute(
name: "ReviewPost",
url: "{year}/{month}/{filename}/",
defaults: new {controller = "ReviewPost", action = "Detail"},
namespaces: new[] {"ApplicationName.Website.Controllers"},
constraints: new {year = #"\d{4}", month = #"\d{2}"}
);
And I'm able to retrieve the correct RouteData object like so:
string url = "~/ReviewPost/Detail/?year=2015&month=05&filename=review-title";
RouteData routeData = RouteDataUtils.RouteByUrl(myUrl);
However I'm having difficulty figuring out how to generate the friendly URL that should look like the one specified in my configuration (/2015/05/review-title/).
Is the RouteData object able to create an instance of the formatted URL above, or do I have to format it myself? Or does the MVC framework have a class for correctly formatting the URL string using the RouteData object?
Any help would be appreciated.
Update
Try it this way:
var urlHelper = new UrlHelper();
var theUrl = urlHelper.RouteUrl(routeData.Values);
original
Try something like this:
var urlHelper = new UrlHelper();
var theUrl = urlHelper.RouteUrl("ReviewPost",routeData.Values);
Note that the first parameter to RouteUrl is the name of your route--i.e. how you named it in MapRoute.
I am using the following code to get data from my api:
using (var client = new HttpClient())
{
try
{
string url = "http://localhost:58639/api/cars/" + carId + "?includeOwners=true";
var model = client
.GetAsync(url)
.Result
.Content.ReadAsAsync<Car[]>().Result;
Car c = model[0];
newCount = c.Persons.Count;
/* More Code */
}
}
using this route in WebApiConfig:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Is there a way to create the URL dynamically such that if the site was hosted somewhere other than localhost this would still work? I have attempted to do this with Url.RouteUrl and UrlHelper, yet I can't find a way to include the "?includeOwners=true" filter with them.
One way is to put the server part in a config file (web.config etc) and read it from there when you're constructing the url.
Just add the base url part in an appSetting and read it using ConfigurationManager.AppSettings["NameOfKey"]
Please try the below code:
string domainName = ((System.Web.HttpContextWrapper)Request.Properties["MS_HttpContext"]).Request.ServerVariables["HTTP_HOST"];
you can dynamically load the Host and Port or the whole domainname.
In an existing C# Web project here at my Job I've added a Web API part.
In four of my own classes that I use for the Web API I need to access some of the existing Controller-classes. Right now I just create a new Instance of them and everything works as intented: ProductController controller = new ProductController();
Still, creating a new ProductController while one should already exist obviously isn't a good practice. I know the Controllers are created in the Config-file in the Routes.MapHttpRoute, since it's using the C# Web MVC method. Below I've copied that piece of code:
config.Routes.MapHttpRoute(
name: "Default",
routeTemplate: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "MyProject.Controllers" }
);
route.DataTokens["UseNamespaceFallback"] = false;
I've tried to access these Controllers in my one of my API-classes like so:
private void getControllerInstance()
{
var url = "~/Products";
// Original path is stored and will be rewritten in the end
var httpContext = new HttpContextWrapper(HttpContext.Current);
string originalPath = httpContext.Request.Path;
try
{
// Fake a request to the supplied URL into the routing system
httpContext.RewritePath(url);
RouteData urlRouteData = RouteTable.Routes.GetRouteData(httpContext);
// If the route data was not found (e.g url leads to another site) then authorization is denied.
// If you want to have a navigation to a different site, don't use AuthorizationMenu
if (urlRouteData != null)
{
string controllerName = urlRouteData.Values["controller"].ToString();
// Get an instance of the controller that would handle this route
var requestContext = new RequestContext(httpContext, urlRouteData);
var controllerFactory = ControllerBuilder.Current.GetControllerFactory();
// TODO: Fix error (The controller for path '/Products' was not found or does not implement IController.) on this line:
var controllerbase = (ControllerBase)controllerFactory.CreateController(requestContext, controllerName);
controller = (ProductController)controllerbase;
}
}
finally
{
// Reset our request path.
httpContext.RewritePath(originalPath);
}
}
As you might have noticed by the TODO-comment, at the line var controllerbase = (ControllerBase)controllerFactory.CreateController(requestContext, controllerName);, I get the following error:
HttpException was unhandler by user code: The controller for path '/Products' was not found or does not implement IController.
Does anyone know how to fix this error? Has this got something to do with one of the following two lines of the code in the Config-file?
namespaces: new[] { "MyProject.Controllers" }
route.DataTokens["UseNamespaceFallback"] = false;
Or did I do something else wrong?
A tip to everyone: Don't continue programming when you are very, very tired.. Anyway, everything was correct except for a small flaw:
My API Controller is called ProductsController and my normal (default) controller is called ProductController. In the method above I use:
var url = "~/Products";
To access the ProductController..
So, after removing the "s" (and for good measure make everything lower case) I have the following instead:
var url = "~/product";
And now it works..
I've the following ASP.NET WebAPI binding:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new {id = RouteParameter.Optional}
);
And my Controller looks like this:
public class ReferenceDataController : BaseController
{
[RequireUserToken(ApprovedDeviceToken = true, ValidUserToken = true)]
[HttpPost]
public IEnumerable<SynchronizeItem<IReferenceDataItem>> Sync([FromBody]IEnumerable<SynchronizeItem<IReferenceDataItem>> clientSyncItems, [FromUri]int referenceDataType)
{
// my code
}
On the client site I use the following code to send a request:
var client = new RestClient (baseUrl);
var request = new RestRequest (resource, method);
request.XmlSerializer = new JsonSerializer ();
request.RequestFormat = DataFormat.Json;
request.AddHeader ("X-Abc-DeviceToken", deviceToken);
if (!string.IsNullOrWhiteSpace (userToken))
request.AddHeader ("X-Abc-UserToken", userToken);
if (payload != null)
request.AddBody (payload);
if (parameters != null)
{
foreach (var parameter in parameters)
{
request.AddUrlSegment(parameter.Key, parameter.Value);
}
}
var response = client.Execute<T> (request);
My expectation is, sending a POST request to http://myhost/api/referencedata/sync?referencedatatype=countries with a body which contains an IEnumerable. If I remove the UrlSegment parameters on client site and the second argument on the webservice site, than it works.
How can I combine a body with payload and additional URL parameters?
You can define your action method as follow,
[RequireUserToken(ApprovedDeviceToken = true, ValidUserToken = true)]
[HttpPost]
public IEnumerable<SynchronizeItem<IReferenceDataItem>> Sync(IEnumerable<SynchronizeItem<IReferenceDataItem>> clientSyncItems, int referenceDataType)
{
// my code
}
No BodyAttribute or FromUriAttribute. In that way, Web API will try to use a MediaTypeFormatter to deserialize the body into the clientSyncItems collection and any additional value type from the query string (referenceDataType from the query string). The route as you defined it will take "sync" as Id (which would be ignored as it is not a parameter in your action).
You must also specify a content-type header so Web API can choose the right formatter (json or xml for example).