I want to get a path by name, but I can't find which function I can use.. the iron-router guid is not that clear.. Thank you!!
Router.route('/path', {
name: 'newsPage'});
var path = Router.getPath('newsPage');// something like this
That woud be Router.path("newsPage").
You can pass this function 2 additional parameters :
a context object (key / value dictionary) whose keys will be replaced in the path, ie if your route path is /user/:username then if you call Router.path("userProfile",Meteor.user()), you will get the path to the currently connected user profile.
an object to indicate query string parameters and hash value, ie this call Router.path("newsPage",{},{query:{ts:Date.now()},hash:"about"}) will give you this path : /path?ts=1433109536938#about.
Related
I'm trying to figure it out how to build a query string with some important information to be fetched. For example, I have this struct I'm going to decode the query into:
SomeObject{
Names []string
Attr Attribute
}
Atribute{
Group string
City string
}
So, initially I understand passing the names in the query string should look like this:
HTTP://localhost:8000/api/retrieve?names=oneName&names=anotherName
And I can get the names[oneName anotherName] correctly. But now I must build the query to get the attributes in order to get: attributes{group{someGroup} city{Delhi}}. How should the query string be written????
Question it's not related to the HTTP request handlers, but how the params should look to get correctly
Thanks in advance
My API won't enter in the good method when I use this url:
myserver/api/structures/close.
/* #Rest\Put("structures/close")
It enters int the method of this url:
myserver/api/structures/{id}
/* #Rest\Put("structures/{id}")
But I would like to enter in the first method. What should I do ?
I use Symfony 3, Doctrine 2
You have 2 options here:
Put structures/{id} route to the end of the file, so that structures/order route will be matched first.
Restrict route's id parameter to be integer only (not sure if this would work)
#Rest\Put("structures/{id}", requirements={"id": "\d+"})
I am developing Web Application using ASP.NET MVC in C#. But I am having a problem with retrieving full or absolute url. In ASP.NET MVC we get url like this. Url.Content("~/path/to/page"). It will return "path/to/page". But what I want to do is I have a string like this - "~/controller/action".
Let's consider my website domain is www.example.com. If I use Url.Content("~/controller/action"), it will just return "controller/action". I want to get "www.example.com/controller/action". How can I get it?
If you can use the Controller / Action Names...
You should use the Url.Action() method for this.
Typically, Url.Action() will return something similar to what you presently expect when provided with just the Controller and Action names :
// This would yield "Controller/Action"
Url.Action("Action","Controller");
However, when you pass in the protocol parameter (i.e. http, https etc.) then the method will actually return a complete, absolute URL. For the sake of convienence, you can use the Request.Url.Scheme property to access the appropriate protocol as seen below :
// This would yield "http://your-site.com/Controller/Action"
Url.Action("Action", "Controller", null, Request.Url.Scheme);
You can see an example of this in action here.
If you only have a relative URL string...
If you only have access to something like a relative URL (i.e. ~/controller/action), then you may want to create a function that will extend the current functionality of the Url.Content() method to support serving absolute URLs :
public static class UrlExtensions
{
public static string AbsoluteContent(this UrlHelper urlHelper, string contentPath)
{
// Build a URI for the requested path
var url = new Uri(HttpContext.Current.Request.Url, urlHelper.Content(contentPath));
// Return the absolute UrI
return url.AbsoluteUri;
}
}
If defined properly, this would allow you to simply replace your Url.Content() calls with Url.AbsoluteContent() as seen below :
Url.AbsoluteContent("~/Controller/Action")
You can see an example of this approach here.
The following will render a full url, including http or https:
var url = new UrlHelper(System.Web.HttpContext.Current.Request.RequestContext);
var fullUrl = url.Action("YourAction", "YourController", new { id = something }, protocol: System.Web.HttpContext.Current.Request.Url.Scheme);
Output
https://www.yourdomain.com/YourController/YourAction?id=something
In short: is there a way to know if a typescript parameter is required and/or has a default value?
Longer version:
Say I have the following file:
//Foo.ts
class Bar {
foo(required:string,defaultValue:number=0,optional?:boolean) {
...
}
}
I would like to know of each of the parameters:
the name
the type
is it required?
does it have a default value?
I have succesfully used method decorators with the TypeScript reflection API to get the types of the parameters, I've used this method to get their names, but so far I have not found a way to know if a variable is required and/or has a default value.
I know the typescript compiler itself can be used from within typescript. So I'm wondering if there is a way to use the parse tree of the compiler to see if a parameter is required and/or has a default value?
How would that work?
If you want to do this from scratch...
On a high level, one way of doing it is to:
Figure out how to get the SourceFile node using the compiler api of your file. That requires a bit of an explanation in itself.
From there, use the api's forEachChild function to loop over all the nodes in the file and find the node with a kind of SyntaxKind.ClassDeclaration and .name property with text Bar.
Then loop over all the children of the class by again using the api's forEachChild function and get the ones that has the kind SyntaxKind.MethodDeclaration and .name property with text foo.
To get the parameters, you will need to loop over the method node's parameters property.
Then for each parameter node, to get the name you can call .getText() on the .name property.
You can tell if the parameter is optional by doing:
const parameterDeclaration = parameterNode as ts.ParameterDeclaration;
const isOptional = parameterDeclaration.questionToken != null || parameterDeclaration.initializer != null || parameterDeclaration.dotDotDotToken != null;
Or you could use the TypeChecker's isOptionalParameter method.
To get its default expression, you will just have to check the initializer property:
propertyDeclaration.initializer;
To get the type use the TypeChecker's getTypeOfSymbolAtLocation method and pass in the symbol of the node... that gets a little bit complicated so I won't bother explaining it (think about how it's different with union types and such).
Don't do it from scratch...
I've created a wrapper around the TypeScript compiler api. Just use this code with ts-simple-ast (edit: Previously this talked about my old ts-type-info library, but ts-simple-ast is much better):
import { Project } from "ts-morph";
// read more about setup here:
// https://ts-morph.com/setup/adding-source-files
const project = new Project({ tsConfigFilePath: "tsconfig.json" });
const sourceFile = project.getSourceFileOrThrow("src/Foo.ts");
const method = sourceFile.getClassOrThrow("Bar").getInstanceMethodOrThrow("foo");
Once you have the method, it's very straightforward to get all the information you need from its parameters:
console.log(method.getName()); // foo
for (const param of method.getParameters()) {
console.log(param.getName());
console.log(param.getType().getText());
console.log(param.isOptional());
console.log(param.getInitializer() != null);
}
I'm trying to figure out whats the best way to have multiple Get actions in a REST controller.
I would like to do something like this:
Get By Id:
public ResponseType Get(Guid id)
{
// implementation
}
Get By Enum Type:
public ResponseType Get(EnumType type)
{
// implementation
}
Get By Other Enum Type:
public ResponseType Get(OtherEnumType otherType)
{
// implementation
}
etc..
Now when I do something like that, I get the next error message:
Multiple actions were found that match the request
I understand why I get the message and I was thinking how is the best way to do something like that (I want to stick with REST).
I know I can add a route like this:
routeTemplate: "api/{controller}/{action}/{id}"
But then I would need to change the action names and the urls - And this seems like a workaround when we are talking about rest.
Another thing I thought was to create multiple controllers with one Get - But that seems even wronger.
The third workaround was to handle one Get action with an input param that will have the state:
public ResponseType Get(ReqeustObj obj)
{
switch(obj.RequestType)
{
case RequestType.GetById:
// etc...
}
}
Anyway, I would like to know whats the best way to do something like that in REST (WebApi).
As you now, when Web API needs to choose an action, if you don't specify the action name in the route, it looks for actions whose name starts with the method name, GET in this case. So in your case, it will find multiple methods.
But it also try to match the parameters. So, if you include the parameters as part of the url (route parameters) or the query string, the action selector will be able to choose one of the available methods.
If you don't specify a parameter or specify the id in the url (or even in the query string) it should invoke the first overload. If you add the parameter name of the second action in the query string like this: ?type=VALUE it should choose the corresponding overload, and so on.
The question is that the parameter names must be different, or it will not be able to choose one or the other among all the overloads.
For example, if you use the urls in the comments in your browser, you'll see how the right method is chosen:
public class TestController : ApiController
{
// GET api/Test
public string Get()
{
return "without params";
}
// GET api/Test/5
public string Get(int id)
{
return "id";
}
// GET api/Test?key=5
public string Get(string key)
{
return "Key";
}
// GET api/Test?id2=5
public string Get2(int id2)
{
return "id2";
}
}
NOTE: you can also use route constraints to invoke differet methods without using query string parameters, but defining different route parameter names with different constraints. For example you could add a constraint for id accepting only numbers "\d+" and then a second route which accepts "key" for all other cases. In this way you can avoid using the query string