β why IActionResult and why not ActionResult?
It's recommended to use IActionResult as the return type when we are returning any action method, but why are we using the interface? Why not just ActionResult? I've also seen while returning a dictionary we use IDictionary as the return type, why is it like this? I know interfaces contain definition of methods which has to be implemented when inherited by a class.
72 Replies
When a controller action returns an object directly, it will only be able to return 200 OK, 401 Unauthorized or 500 Error (unless you have some exception middlware, but lets assume not for now)
If you want more control over the return code, thats when ActionResult and IActionResult come in
it allows you to use the helper methods on the controller to change the status code, like
Ok(value);
or BadRequest("error message");
etc
IActionResult is the untyped version of ActionResult and should only be used with MVC
if this is an API, always use ActionResult<T>
It's not just the status code right? What I've learnt is if i had to return multiple types of data types (not at the same time) like contentresult or fileresult we use IActionResult since it's the interface which is implemented by all the action results
But still, why do we keep interface as the return type instead of a class?
Why not?
But yeah, if you need FileResult you'd probably also use that as your return type. I've used FileResult a grand total of maybe once or twice in my entire 20 years of C# π
Usually if I'd want to return a string, Don't we just
Public string method1(){
Return "rjdjr";
}
But not
Public Istring method1(){
Return "rjdjr";
}
Right?
Correct, but string is a very bad example here π
all these implement
IActionResult
Right
that means they are all considered valid returns for a method that says it returns
ActionResult
Why i said string because i was comparing with dictionary
If you want to return a dictionary, you either return the dictionary, or
ActionResult<Dictionary<TKey, TValue>>
depends on if you need to be able to change the status code or notAhh! Apologies maybe i should have created another post about string and IDictionary
we're still talking about controllers and actions, right? :p
Yes, kinda. But what i want to know is in general why do we have interfaces as return types instead of class be it mvc or in general
because sometimes you dont know all the implementations
what if someone wants to be able to add their own implementation to your library?
or you add something else down the line
interfaces allow loose coupling
I saw somewhere with the return type of IDictionary instead of Dictionary and here in MVC it's IActionResult instead of ActionResult, so why interface instead of class, i was curious about that.
You mean, as long as i inherit the interface, i can create a class basically and that can be used by someone else by implementing the interface of the class?
That's the crux of it right?
For example in case of MVC, i can create a maybe Yamlresult class which inherits the IActionResult interface.
yes, exactly
And someone can return the YamlResult using IActionResult as the return type
using interfaces in methods as both inputs and outputs allow you to very clearly specify whats important, and allow future code changes to be more smooth
I understood, but what's the scene with us never using Istring or Iint as return type?
those interfaces dont exist π
interfaces are for complex types, not primitives
Ohh primitive types
Right right
Since dictionary isn't primitive, we use IDictionary
IList etc...
yeah. If it makes sense.
You don't have to return the interface
in some cases you want to, in some cases you don't.
most BCL (base class library) classes also implmenent several interfaces
a
List<T>
implements not only IList<T>
but also IReadOnlyList<T>
which means we can have a list, but return it as readonly, if we don't intend the caller to mutate it
it shows our intentions betterOhhhh! So the return type can be Ireadonlylist<t> and we return the list
And it means like you said, it's only read only
yup
well, it behaves as if it was readonly
you could "get around it" if you really wanted, but thats hacky and bad
I seee, i got it why we use interface as return type.
Thanks @Pobiega
Like, look at this
because
strings
will be IReadOnlyList
, I as a developer can see that "oh im not supposed to modify this"Right right, it makes more sense now.
however
this works, because I KNOW its actually a List<string>
this would crash horribly if it wasn't
Also while implementing IActionResult basically says that the return type can be any of the action results?
yes
this is why we usually avoid returning that
its too broad
in MVC, you dont have much of an option so thats fine
but in an API, you should be as specific as you can be, so
ActionResult<T>
is betterYou're basically converting the read-only list to a normal list and adding a string but if you didn't know that it is a list beforehand it would fail right?
it lets tools like swagger inspect the return type (for the happy case) automatically
correct
Gotcha, I'll try using this
In general, not considering mvc, using interface as return type helps in readability of the code
helps in showing intentions, while also allowing more easy... adaptions/additions
if a system uses interfaces, I can easily add a new type to that system without modifying any code within the system itself
I just make my new type have the correct interfaces and implement them properly
so when we don't plan to return a status code other than those three, then we return the object directly? thats nice to know
yeah, or if you use an exception handling middlware
I'm not personally a fan of using exceptions to handle http status codes, so I don't use it for that.. so most of my endpoints return
ActionResult<T>
but don't most of your endpoints only return 200, 401, and 500?
so return object directly, no?
yes and no.
I like returning bad request on bad requests.
I see
and since I'm a huge fan of result types, I handle the mapping from a negative result => http error in the endpoint
would you mind sharing a sample of that anywhere? here or in new thread or DMs
I guess its about standards and how .NET defines the standards, nothing more. No one limits you to return any object you want but you will not follow the standard, not attaching the status code etc.
I'm not sure how to approach this, would we use an enum for our result type and have a switch statement in the endpoint?
I think he probably means the Result type library and then matching the errors to the status codes properly.
yes
Nick had a video on it. Give me a sec
that would be great π
its a functional programming concept originally, and since we dont have true DUs its not perfect in C#
Nick Chapsas
YouTube
Whatβs the Result Type Everyone Is Using in .NET?
Check out my courses: https://dometrain.com
Become a Patreon and get source code access: https://www.patreon.com/nickchapsas
Hello, everybody, I'm Nick, and in this video, I will introduce you to the Result type in .NET. It might not be a native .NET type but it exists in tons of libraries and codebases so in this video I'll help you understand...
but it has too many upsides to ignore for me π
Its about discriminated unions being possibe to be used in C# in a hacky way - the library is however pretty polished and you wont notice it.
no clue what that is
will have a look
Discriminated unions are in typescript defined like this:
const myType: string | number = "some string but could have been a number as well";
myType = 5;
oh I did know it
just forgot the name
the idea is that you can return you base default result which is T or you return some other which is another class which represents an error.
Then you don't need to rethrow the errors but rather you expect always the posibility that its the result or some possible error results
The advantage is that you will have it in a typesafe way and it will not be possible that you dont cache an error, cause you have to match all possible cases.
great idea
also its more efficient then throwing errors cause throwing errors is expencive
gotta drive to work now
ok
im on vacation
π
the big "split" in result types in C# is wether you are explicit about all the error types a method can throw or not
yea expecting is the right word
Compare
OneOf
(explicit) to Remora.Results
(not explicit)
The downside of being explicit is that your type declarations can get pretty wackyin my oppinion in result type you dont expect as you do expect then 'throw' cause its typesafe
also true
public Result<Movie, ValidationFailed, MovieNotFound, DatabaseError, DannyDevitoNotInMovie> GetByName(string name)
is a fairly annoying method declaration πidk I like it π
in typescript you can use string as type directly making it quicker to write
TS has true DUs thou. C# does not.
we can't emulate it perfectly
I have been using it so far from time to time to define cases where I have one object but it has different states, so its not null or T but rather 'LOADING' | T | 'UNDEIFNED'.
Thats some cases where I would use it
i think in C# its still pretty good
Pobiega, we have been talking on discord once about rust, right?
Its good enough to use for sure, but if you've done TS or F# etc it still not perfect π
maybe? idk
But lets not go offtopic in here
I miss the true functional stuff from F# in C# still, I hope they make progress there
This thread is ready to be closed.
yea, true.