Writing ASP.NET frameworks other than WebForms or MVC? - asp.net

I want to know what "clean" ASP.NET looks like. For example, I want to build my own framework on ASP.NET, and I don't know what assembly I should include.
All books discussing ASP.NET describe either WebForms or MVC, but none explain the ASP.NET layer of things.
What part of ASP.NET is meant in below picture?

Both WebForms and MVC are implemented through a handler, see the ASP.NET Page Handler and MvcHandler Class on MSDN.
Handlers (MSDN: Introduction to HTTP Handlers) are the most lightweight way to utilize ASP.NET. You get access to an HttpRequest instance that knows everything about the request there is to know.
In a handler, you read this HttpRequest, apply your application logic and write the result throught the HttpResponse member instance that an IHttpHandler's HttpContext parameter in ProcessRequest(HttpContext context) has:
namespace HandlerExample
{
public class MyHttpHandler : IHttpHandler
{
// Override the ProcessRequest method.
public void ProcessRequest(HttpContext context)
{
context.Response.Write("<H1>This is an HttpHandler Test.</H1>");
context.Response.Write("<p>Your Browser:</p>");
context.Response.Write("Type: " + context.Request.Browser.Type + "<br>");
context.Response.Write("Version: " + context.Request.Browser.Version);
}
// Override the IsReusable property.
public bool IsReusable
{
get { return true; }
}
}
}
A lot of ASP.NET, if not all, lives in the System.Web namespace.

ASP.NET WebForms and MVC are built on top of the ASP.NET engine, which basically consists of modules, handlers, and the ecosystem around that.
In fact you can write your own framework by writing modules and handlers. You can write your own code that picks up the request and handles it (handler) or adjust existing messages (modules).

We used NancyFX in several projects and it's definitely worth looking into. Simplicity and performance are amazing. You can host it independently or over the IIS (like asp.net). And it's also cross-platform.

Related

Custom Authorize attribute without Identity and OWIN

I would like to construct a custom authorization attribute that does not invoke Identity or OWIN. Essentially, the only thing that it should have access to is a request context and the ability to either tell the MVC framework to process to continue to process the request or deny it.
Question Is there a simple way of achieving this in ASP.NET Core 2?
Some ideas
My understanding of ASP.NET Core is that it provides a way to customize the request pipeline using different middleware. I have seen that there are specific ones that are used for authentication, but they all seem to be very specific to Identity.
Is it better to to use a different type of filter?
A little bit late answer, but still.. the "old" way of overriding attributes comes back with the .Net Core 2.0, where in addition to the base class, you have to implement the IAuthorizationFilter interface:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class CustomAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
{
private readonly string _someFilterParameter;
public CustomAuthorizeAttribute(string someFilterParameter)
{
_someFilterParameter = someFilterParameter;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
// you can play with the context here
}
}
More discussion here

How to tell if code is running on web server without using System.Web?

I have a code library I have written which can be utilized in both desktop applications and on a web server. That library sometimes needs to know which environment it's running in.
In the past I have relied on System.Web.Hosting.HostingEnvironment.IsHosted to tell if the code is running on a web server. Unfortunately asp.net core mvc does not have access to the System.Web namespace so I need another mechanism.
How can the code tell if it's running on a web server if one of those possibilities is asp.net core mvc?
Answering my own question in case it helps others.
It's been mentioned that one way to determine whether the code is running on a web server or desktop app is to look at the name of the process it's running in. This is definitely possible, but I have little control over what the process name is for a web application and the name is likely to change in the future if history is any indication.
So instead, I chose to make the determination based on the application's config file name. This file name is different for web apps and desktop apps and it's something that's more under my control as a developer.
The method I wrote to do this is:
public bool IsWebServer {
get {
string file = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile.ToLower();
//web.config used by asp.net 4.X,
//app.config used by MVC Core
//NameOfTheApp.exe.config used by desktop applications
if(file.Contains("web.config") || file.Contains("app.config")) {
return true;
}
return false;
}
}
Unfortunately, there is no currently equivalent API. When you look at how that property works, you can easily do something equivalent yourself--without making assumptions about which server is hosting your application.
You'll have to set up your API with a static public property:
namespace My.Project
{
public static HostingEnvironment
{
public static bool IsHosted { get; private set; }
public static void SetIsHosted(this IServicesCollection services)
{
// you can grab any other info from your services collection
// if you want. This is an extension method that you call
// from your Startup.ConfigureServices method
IsHosted = true;
}
}
}
So now you have something that works with both ASP.Net MVC 5 and 4.5. You would integrate it in your Startup.ConfigureServices() method.
public void ConfigureServices(IServiceCollection services)
{
// Set up whatever services you want here.
// Make sure you have your My.Project namespace
// in your using statements so you can use the IsHosted()
// extension method
services.SetIsHosted();
}
The only difference between this solution and the legacy System.Web.Hosting.HostingEnvironment.IsHosted solution is that the flag was set by the framework when the application was started by IIS automatically. This is probably as close of an equivalent solution as you are going to get, while still allowing the ability to host anywhere.

Why is accessing session state and HttpContext in WebAPI considered bad design?

I have several .asmx web services that I want to upgrade to WebAPI. These web services look somewhat like this:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class TheWebService : System.Web.Services.WebService {
[WebMethod(EnableSession = true)]
public string SomeMethod(string SomeInput)
{
MySessionModel TheSession = HttpContext.Current.Session["UserSession"] as MySessionModel;
return SomeClass.SomeMethod(SomeInput, TheSession);
}
}
Basically, I have a single-page application. I'm using Forms Auth to login and redirect users to their "profile" and then, from this page, the app uses web services to communicate with the server. The web services only return raw strings so I don't need serialization at teh web service level. For the moment, the app is hosted in IIS and soon I'll be deploying it into azure.
I've looked around on the web, and several posts suggest that using session state and HttpContext is bad design. Why is using HttpCurrent and session state a bad idea in this case?
There is nothing innately wrong with using ASP.NET Session, as long as you don't use it as a catch-all basket for any old data. Shopping carts, for example, do not belong in Session: they belong in a Shopping Cart persistence component.
Also, and I suspect the reason for the Azure tag on this question, if you are running in a load-balanced environment such as an Azure Cloud Service, you need to use an external session provider such as a SQL Database or a shared cache. Using the in-process session provider (the default) will cause very odd, often unreproducable bugs as users are switched between different servers with different copies of the session.
As for HttpContext.Current, well, for Web API, things like Inversion of Control, Dependency Injection, and simple testability are important. A clean, testable Web API version of that service might look something like this:
public class TheWebService : ApiController {
private readonly IUserSession _userSession;
public TheWebService(IUserSession userSession)
{
_userSession = userSession;
}
public string SomeMethod(string SomeInput)
{
MySessionModel TheSession = _userSession.Get();
return SomeClass.SomeMethod(SomeInput, TheSession);
}
}
public interface IUserSession
{
MySessionModel Get();
}
You could still use HttpContext.Current.Session["UserSession"] in a class like this:
public class CurrentContextUserSession : IUserSession
{
public MySessionModel Get()
{
return HttpContext.Current.Session["UserSession"] as MySessionModel;
}
}
You would then use an IoC container such as Unity or Ninject to set CurrentContextUserSession as the implementation of IUserSession for Web API to use when constructing instances of TheWebService. But when you were writing your tests, you could use a mock or stub implementation of IUserSession that had no dependency on HttpContext.Current.
In your specific example, you are using the Session only inside the WebMethod, which is fine as it is already coupled to ASP.NET but many people tend to use this at other layers of their application which is a really bad design.
Common problems of using HttpContext.Current in those layers are:
the code cannot be easily unit tested in isolation
the code is tightly coupled to an ASP.NET context
This being said, having stateful services that depend on the session is bad design. In the example you have shown, that's an ASMX WebService which is depending on the ASP.NET Session state meaning that the client should be passing cookies around in order to invoke this service. Also stateful services are harder to scale.

how i can create a page that works like stackoverflow

i want to know how did these pages work!
like this :
https://stackoverflow.com/questions/ask
there is no extension in end of the address!
is this a way to call webmethods directly?!
i wrote this page , but i think its not right!
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string name= Request.QueryString["name"];
if (Request.PathInfo == "/SayHi")Response.Write( SayHi(name));
}
[WebMethod]
public static string SayHi(string name)
{
return "Hi " + name;
}
//[WebMethod]
//public static string SayHi()
//{
// return "Hi ";
//}
}
For ASP.NET, you can use ASP.NET Routing, which will allow you to separately configure what the URLs should look like.
You can use it both for regular WebForms apps and with the newer ASP.NET MVC.
Take a look at ASP.Net MVC. It's the framework that runs the Stack Overflow site per this other question. MVC uses the routing engine to allow urls without a trailing ".aspx".
StackOverflow uses ASP.NET MVC as its core web technology and you are right there are no extensions, because there is a routing engine that handles requests.
In your example:
http://stackoverflow.com/questions/ask
This would equate to the StackOverflow site invoking a controller named ask and displaying its default view, based upon the rules setup for the routing engine.
Read ASP.NET MVC Routing Overview for more information on how ASP.NET MVC routing works.
UPDATE:
For more information on what software and hardware the StackOverflow site was originally built on, then read What Was Stack Overflow Built With?. This is generally still correct, although some of the hardware and amount of each may have changed with an increased user base.

How to server-side cache ASP.NET custom HttpHandler response

I've got a custom HttpHandler in my ASP.NET application, that basically builds and returns a javascript object. I have no experience with server-side caching, and my (possibly incompetent) google searches aren't returning anything basic enough to get me started.
Could anyone provide a very simple example to give me an idea of how to access and use the server-side cache from a custom HttpHandler, or, leave some links to get me started? Thanks a lot.
Additional info: I'm on IIS 6, and my code-behind is in C# (although a VB example would work as well).
Very simple example to get you started, without locking or error handling:
public void ProcessRequest(HttpContext context) {
MyObject thing = context.Cache["object_name"];
if (thing == null) {
thing = new MyObject();
context.Cache["object_name"] = thing;
}
// use thing here to process request
}

Resources