Method: HttpPost
URL: api/Calculation/CalculratePlus/20/30
Result: 50
This is my code:
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApiPostPlus",
routeTemplate: "api/{controller}/{action}/{id}/{id}",
defaults: new {
id = RouteParameter.Optional,
id2 = RouteParameter.Optional
});
}
This is my controller (I want fixing my controllers and making models). I have no idea...
// GET: api/Calculator/PostPlusValue/item/value2
public HttpResponseMessage PostPlusValue(int i, int y)
{
var response = Request.CreateResponse(HttpStatusCode.Created);
string url = Url.Link("DefaultApiPostPlus", new { id = i, id2 = y});
response.Headers.Location = new Uri(url);
return response;
}
Please let me help..
thx..
I am not sure what you want correctly but you can try this:
config.Routes.MapHttpRoute(
name: "DefaultApiPostPlus",
routeTemplate: "api/{controller}/{action}/{id1}/{id2}",
defaults: new
{
id1 = RouteParameter.Optional,
id2 = RouteParameter.Optional
});
then your action:
// POST: api/Values/PostPlusValue/item/value2
public HttpResponseMessage PostPlusValue(int id1, int id2)
{
var response = Request.CreateResponse(HttpStatusCode.Created);
response.Content = new StringContent((id1 + id2).ToString());
return response;
}
Related
I'm trying to build two routes only to action and to controller with id, keeping the default.
I have to access:
www.mysite.com/MyController/MyAction/{OptionalId}
www.mysite.com/MyController/{OptionalId}
www.mysite.com/MyActionFromHomeController
I was able to create routes to work with first and the third point, but not for the second. Current code:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "OnlyActionToHomeController",
url: "{action}",
defaults: new { controller = "Home" },
constraints: new { noConflictingControllerExists = new NoConflictingControllerExists() }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
public class NoConflictingControllerExists : IRouteConstraint
{
private static readonly Dictionary<string, bool> _cache = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var path = httpContext.Request.Path;
if (path == "/" || String.IsNullOrEmpty(path))
return false;
if (_cache.ContainsKey(path))
return _cache[path];
IController ctrl;
try
{
var ctrlFactory = ControllerBuilder.Current.GetControllerFactory();
ctrl = ctrlFactory.CreateController(httpContext.Request.RequestContext, values["action"] as string);
}
catch
{
_cache.Add(path, true);
return true;
}
var res = ctrl == null;
_cache.Add(path, res);
return res;
}
}
I did!
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "OnlyController",
url: "{controller}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
constraints: new { id = #"\d+" } // define the id parameter needs to be integer
);
routes.MapRoute(
name: "OnlyActionToHomeController",
url: "{action}",
defaults: new { controller = "Home" },
constraints: new { noConflictingControllerExists = new NoConflictingControllerExists() }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
public class NoConflictingControllerExists : IRouteConstraint
{
private static readonly Dictionary<string, bool> _cache = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var path = httpContext.Request.Path;
if (path == "/" || String.IsNullOrEmpty(path))
return false;
if (_cache.ContainsKey(path))
return _cache[path];
IController ctrl;
try
{
var ctrlFactory = ControllerBuilder.Current.GetControllerFactory();
ctrl = ctrlFactory.CreateController(httpContext.Request.RequestContext, values["action"] as string);
}
catch
{
_cache.Add(path, true);
return true;
}
var res = ctrl == null;
_cache.Add(path, res);
return res;
}
}
I have configured routing like this:
config.Routes.MapHttpRoute(
name: "Sales",
routeTemplate: "api/{Sales}/{jsonresponce}",
defaults: new { controller = "Sales", action = "Postsomething" }
);
config.Routes.MapHttpRoute(
name: "User",
routeTemplate: "api/{User}/{GetDetails}",
defaults: new { controller = "User", action = "GetDetails" }
);
Here is my UserController:
public class UserController : ApiController
{
userservice objservice = new userservice();
[HttpGet]
public CustDetails GetDetails(string Username, string Password, string BillingFeedID)
{
CustDetails model = new CustDetails();
//checking for encrypted password
model.UserName = Username;
model.Password = Password;
model.BillingFeedID = BillingFeedID;
model = objservice.Login(model);
//taking merchant configuration data
var data = objservice.Getcustomerconfig(model.MerchantID, BillingFeedID);
model.LastPosBillID = data.LastPosBillID;
model.LastTimeStamp = data.LastTimeStamp;
model.SyncStatus = data.SyncStatus;
model.SynsTimeInterval = data.SynsTimeInterval;
model.DataSorce = data.DataSorce;
model.DataAuthentication = data.DataAuthentication;
model.DataBaseQuery = data.DataBaseQuery;
return model;
}
}
I also have a SalesController:
public class SalesController : ApiController
{
[HttpPost]
public async Task<HttpResponseMessage> PostSomething()
{
StringBuilder sb = new StringBuilder();
try
{
string jsonData = await Request.Content.ReadAsStringAsync();
// dynamic dataList = JArray.Parse(jsonData);
if (File.Exists(#"C:\MCarrots\Umairbills\Umairbills.json"))
File.Delete(#"C:\MCarrots\Umairbills\Umairbills.json");
File.Create(#"C:\MCarrots\Umairbills\Umairbills.json").Close();
File.WriteAllText(#"C:\MCarrots\Umairbills\Umairbills.json", jsonData);
return Request.CreateResponse(HttpStatusCode.OK, "OK");
}
catch (Exception ex)
{
File.WriteAllText(#"C:\MCarrots\mcarrots\Umairbills.json", ex.ToString());
return Request.CreateResponse(HttpStatusCode.NoContent, ex.ToString());
}
}
When I try to call the GetUserDetails action with this url:
http://localhost:42945/api/User/GetDetails?Username=kay001&Password=kay501&BillingFeedID=KF1
It is throwing this error:
"Message":"The requested resource does not support http method"
But the POST method in SalesController is working.
Your route templates seem off. I think they should be:
config.Routes.MapHttpRoute(
name: "Sales",
routeTemplate: "api/Sales/{action}",
defaults: new { controller = "Sales", action = "Postsomething" }
);
config.Routes.MapHttpRoute(
name: "User",
routeTemplate: "api/User/{action}",
defaults: new { controller = "User", action = "GetDetails" }
);
I changed the route templates so that the controller name is essentially hard-coded, and the action is a placeholder. The action can be left out in this case though, defaulting to GetDetails.
I just Register these routes now how can I get Apikey value in WebApiKeyHandler.cs since it is not part of query string so I am getting null. Also guide me how I am validating keys is best practice for Web Api Project?
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi2",
routeTemplate: "api/v1/users/{apikey}/{controller}/{action}/",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/v1/users/{apikey}/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.MessageHandlers.Add(new WebApiKeyHandler()); // global message handler
}
WebApiKeyHandler.cs
public class WebApiKeyHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
string apikey = HttpUtility.ParseQueryString(request.RequestUri.Query).Get(Constants.API_KEY_QUERY_STRING);
if (string.IsNullOrWhiteSpace(apikey))
{
HttpResponseMessage response = request.CreateErrorResponse(HttpStatusCode.Forbidden, ErrorCodes.API_KEY_EMPTY_ERROR);
var tsc = new TaskCompletionSource<HttpResponseMessage>();
tsc.SetResult(response);
return tsc.Task;
}
else if (!ValidateKey(apikey))
{
HttpResponseMessage response = request.CreateErrorResponse(HttpStatusCode.Forbidden, ErrorCodes.API_KEY_INVALID_ERROR);
var tsc = new TaskCompletionSource<HttpResponseMessage>();
tsc.SetResult(response);
return tsc.Task;
}
else
{
return base.SendAsync(request, cancellationToken);
}
}
private static bool ValidateKey(string apiKey)
{
Guid key;
Guid.TryParse(apiKey, out key);
return new StAccountsDomainContext().ApiSubscriptions.Any(x => x.ApiKey == key && x.IsActive == true && !x.ApiIBlacklists.Any());
}
private static bool ValidateSecretKey(string apiKey, string secretKey)
{
Guid key1;
Guid.TryParse(apiKey, out key1);
Guid key2;
Guid.TryParse(secretKey, out key2);
return new StAccountsDomainContext().ApiSubscriptions.Any(x => x.ApiKey == key1
&& x.SecretKey == key2
&& x.IsActive == true
&& !x.ApiIBlacklists.Any());
}
}
You can use the GetRouteData() extension on HttpRequestMessage to get the route data. Example: request.GetRouteData().Values
My case is very similar to this question, but since he did not get an answer I thought I'd throw some more input.
Everything works fine locally (on the VS embedded server). When I deploy to Azure, I get a 404 error accompanied by "No type was found that matches the controller named...".
However, when I load the routedebugger module the mapping seems ok even on Azure.
What can I do to debug that problem?
Thanks,
Alex
Edit: my routes are created this way:
GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
};
GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Edit 2: Here my controller class
public class EmployeeController : ApiController
{
// GET api/<controller>
public IEnumerable<Employee> Get()
{
using (var context = new nws())
{
return context.Employees;
}
}
// GET api/<controller>/5
public Employee Get(int id)
{
using (var context = new nws())
{
return context.Employees.FirstOrDefault(e => e.ID == id);
}
}
// GET api/<controller>/getbyatid/5
public Employee GetByAtId(string id)
{
using (var context = new nws())
{
return context.Employees.FirstOrDefault(e => e.AtUserID == id);
}
}
// POST api/<controller>
public void Post([FromBody]string value)
{
}
// PUT api/<controller>/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/<controller>/5
public void Delete(int id)
{
}
// GET api/<controller>/timebank/5
public int? GetTimeBank(string id)
{
using (var context = new nws())
{
var employee = context.Employees.FirstOrDefault(e => e.AtUserID == id);
if (employee != null)
return employee.GetTimeBank();
return null;
}
}
}
Switch the order of routes and try again.
GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
GlobalConfiguration.Configuration.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
};
I got an error - No action was found on the controller 'Action' that matches the request.
The url is http://localhost:37331/api/action/FindByModule/1.
The routing I used is
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Controller:
public class ActionController : ApiController
{
private IActionRepository repository = null;
[HttpGet]
[ActionName("All")]
public IEnumerable<JsonAction> All()
{
return from action in this.repository.Get()
select new JsonAction
{
ID = action.ID,
Text = action.Text.Trim(),
Description = action.Description.Trim(),
};
}
[HttpGet]
[ActionName("FindByModule")]
public IEnumerable<JsonAction> FindByModule(Int64 moduleId)
{
return from action in this.repository.FindByModule(moduleId)
select new JsonAction
{
ID = action.ID,
Text = action.Text.Trim(),
Description = action.Description.Trim(),
};
}
}
This is because there is a parameter name mismatch. From your route the value 1 is assigned to parameter named id and your action is looking for parameter named moduleId.
First option is to change your route like this:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{moduleId}",
defaults: new { moduleId = RouteParameter.Optional }
);
Second is to change your URL like this:
http://localhost:37331/api/action/FindByModule?moduleId=1
So the parameter name match.
My api had too many parameters and I was getting an error. I solved the problem with Route.
[Route("addressverification/{id}/{no}/{day}/{month}/{year}")]
public AdressVerificationResult Get(long? id, long? no ,long? day, long? month, long? year)
{
return new AdressVerificationResult
{
Aciklama = "19........4 kimlik numaralı kişinin 18.......1 adres numarasında 'YerlesimYeri' adres tipi için geçerli bir yurtiçi adres beyanı mevcuttur.",
DurumKod = true
};
}