Issue 1:
The Bug

flask.views.View does not properly handle conversion of an async dispatch_request, resulting in a coroutine that is never awaited.

flask.views.MethodView does not properly handle conversion of async methods, resulting in coroutines that are never awaited.

Replication

Create an async dispatch_request method on a View, or a get method on a MethodView.

Add the view to the app using the View.as_view() and app.add_url_rule() functions.

Access the route and observe a crash and 500 status code.

The following application reproduces the bug.

from flask import Flask
from flask.views import View, MethodView

app = Flask("MyApp")

class TestAsyncView(View):
async def dispatch_request(self):
return 'ASYNC VIEW RESPONSE'

class TestAsyncMethodView(MethodView):
async def get(self):
return 'ASYNC METHODVIEW GET RESPONSE'

app.add_url_rule("/async_view", view_func=TestAsyncView.as_view("test_async_view"))
app.add_url_rule('/async_methodview', view_func=TestAsyncMethodView.as_view('test_async_methodview'))

if __name__ == "__main__":
app.run(port=8000)

The following error occurs after running curl localhost:8000/async_view:

Traceback (most recent call last):
File "/Users/tpansino/NewRelic/Testing/Flask2Bug/flask/src/flask/app.py", line 2073, in wsgi_app
response = self.full_dispatch_request()
File "/Users/tpansino/NewRelic/Testing/Flask2Bug/flask/src/flask/app.py", line 1519, in full_dispatch_request
return self.finalize_request(rv)
File "/Users/tpansino/NewRelic/Testing/Flask2Bug/flask/src/flask/app.py", line 1538, in finalize_request
response = self.make_response(rv)
File "/Users/tpansino/NewRelic/Testing/Flask2Bug/flask/src/flask/app.py", line 1730, in make_response
raise TypeError(
TypeError: The view function did not return a valid response. The return type must be a string, dict, tuple, Response instance, or WSGI callable, but it was a coroutine.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>500 Internal Server Error</title>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p>

Expected Behavior

Asynchronous dispatch_request functions and methods should either be:

Converted using async_to_sync before being returned from as_view().

Executed or awaited in the application when a route is accessed.

Environment

Python version: 3.9.5

Flask version: 2.0.1

Issue 2:
Regular views can now be written as async functions, but instances of the View and MethodView classes did not get updated to support this functionality. Consider the following example:

import asyncio
from flask import Flask
from flask.views import View, MethodView

app = Flask(__name__)

class Test(View):
async def dispatch_request(self):
await asyncio.sleep(1)
return 'test'

class Test2(MethodView):
async def get(self):
await asyncio.sleep(1)
return 'test2'

app.add_url_rule('/test', view_func=Test.as_view('test'))
app.add_url_rule('/test2', view_func=Test2.as_view('test2'))

The expectation is that you should be able to send requests to /test and /test2 and that their respective handlers should be wrapped with the app.ensure_sync() method, as function-based handlers are.

Instead sending requests to these URLs cause the following error:

TypeError: The view function did not return a valid response. The return type must be a string, dict, tuple, Response instance, or WSGI callable, but it was a coroutine.

Environment:

Python version: >= 3.7

Flask version: >= 2