[.NETWorld] Asynchronous TCP Sockets as an Alternative to WCF

In a Microsoft technologies environment, using Windows Communication Foundation (WCF) is a common approach for creating a client-server system. There are many alternatives to WCF, of course, each with its own advantages and disadvantages, including HTTP Web Services, Web API, DCOM, AJAX Web technologies, named pipe programming and raw TCP socket programming. But if you take into account factors such as development effort, manageability, scalability, performance and security, in many situations using WCF is the most efficient approach.

However, WCF can be extremely complicated and might be overkill for some programming situations. Prior to the release of the Microsoft .NET Framework 4.5, asynchronous socket programming was, in my opinion, too difficult in most cases to justify its use. But the ease of using the new C# await and async language features changes the balance, so using socket programming for asynchronous client-server systems is now a more attractive option than it used to be. This article explains how to use these new asynchronous features of the .NET Framework 4.5 to create low-level, high-­performance asynchronous client-server software systems.

The best way to see where I’m headed is to take a look at the demo client-server system shown in Figure 1. At the top of the image a command shell is running an asynchronous TCP socket-based service that accepts requests to compute the average or minimum of a set of numeric values. In the middle part of the image is a Windows Forms (WinForm) application that has sent a request to compute the average of (3, 1, 8). Notice the client is asynchronous—after the request is sent, while waiting for the service to respond, the user is able to click on the button labeled Say Hello three times, and the application is responsive.

Demo TCP-Based Service with Two Clients
Figure 1 Demo TCP-Based Service with Two Clients

The bottom part of Figure 1 shows a Web application client in action. The client has sent an asynchronous request to find the minimum value of (5, 2, 7, 4). Although it’s not apparent from the screenshot, while the Web application is waiting for the service response, the application is responsive to user input.

In the sections that follow, I’ll show how to code the service, the WinForm client and the Web application client. Along the way I’ll discuss the pros and cons of using sockets. This article assumes you have at least intermediate-level C# programming skill, but does not assume you have deep understanding or significant experience with asynchronous programming. The code download that accompanies this article has the complete source code for the three programs shown in Figure 1. I have removed most normal error checking to keep the main ideas as clear as possible.

Creating the Service

The overall structure of the demo service, with a few minor edits to save space, is presented in Figure 2. To create the service, I launched Visual Studio 2012, which has the required .NET Framework 4.5, and created a new C# console application named DemoService. Because socket-based services tend to have specific, limited functionality, using a more descriptive name would be preferable in a real-life scenario.

Figure 2 The Demo Service Program Structure

  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.IO;
  5. using System.Threading.Tasks;
  6. namespace DemoService
  7. {
  8.   class ServiceProgram
  9.   {
  10.     static void Main(string[] args)
  11.     {
  12.       try
  13.       {
  14.         int port = 50000;
  15.         AsyncService service = new AsyncService(port);
  16.         service.Run();
  17.         Console.ReadLine();
  18.       }
  19.       catch (Exception ex)
  20.       {
  21.         Console.WriteLine(ex.Message);
  22.         Console.ReadLine();
  23.       }
  24.     }
  25.   }
  26.   public class AsyncService
  27.   {
  28.     private IPAddress ipAddress;
  29.     private int port;
  30.     public AsyncService(int port) { . . }
  31.     public async void Run() { . . }
  32.     private async Task Process(TcpClient tcpClient) { . . }
  33.     private static string Response(string request)
  34.     private static double Average(double[] vals) { . . }
  35.     private static double Minimum(double[] vals) { . . }
  36.   }
  37. }

After the template code loaded into the editor, I modified the using statements at the top of the source code to include System.Net and System.Net.Sockets. In the Solution Explorer window, I renamed file Program.cs to ServiceProgram.cs and Visual Studio automatically renamed class Program for me. Starting the service is simple:

  1. int port = 50000;
  2. AsyncService service = new AsyncService(port);
  3. service.Run();

Each custom socket-based service on a server must use a unique port. Port numbers between 49152 and 65535 are generally used for custom services. Avoiding port number collisions can be tricky. It’s possible to reserve port numbers on a server using the system registry ReservedPorts entry. The service uses an object-oriented programming (OOP) design and is instantiated via a constructor that accepts the port number. Because service port numbers are fixed, the port number can be hardcoded rather than passed as a parameter. The Run method contains a while loop that will accept and process client requests until the console shell receives an <enter> key press.

The AsyncService class has two private members, ipAddress and port. These two values essentially define a socket. The constructor accepts a port number and programmatically determines the IP address of the server. Public method Run does all the work of accepting requests, then computing and sending responses. The Run method calls helper method Process, which in turn calls helper Response. Method Response calls helpers Average and Minimum.

There are many ways to organize a socket-based server. The structure used in the demo tries to strike a balance between modularity and simplicity, and has worked well for me in practice.

The Service Constructor and Run Methods

The two public methods of the socket-based demo service are presented in Figure 3. After storing the port name, the constructor uses method GetHostName to determine the name of the server, and to then fetch a structure that contains information about the server. The AddressList collection holds different machine addresses, including IPv4 and IPv6 addresses. The InterNetwork enum value means an IPv4 address.

Figure 3 Service Constructor and Run Methods

  1. public AsyncService(int port)
  2. {
  3.   this.port = port;
  4.   string hostName = Dns.GetHostName();
  5.   IPHostEntry ipHostInfo = Dns.GetHostEntry(hostName);
  6.   this.ipAddress = null;
  7.   for (int i = 0; i < ipHostInfo.AddressList.Length; ++i) {
  8.     if (ipHostInfo.AddressList[i].AddressFamily ==
  9.       AddressFamily.InterNetwork)
  10.     {
  11.       this.ipAddress = ipHostInfo.AddressList[i];
  12.       break;
  13.     }
  14.   }
  15.   if (this.ipAddress == null)
  16.     throw new Exception(“No IPv4 address for server”);
  17. }
  18. public async void Run()
  19. {
  20.   TcpListener listener = new TcpListener(this.ipAddress, this.port);
  21.   listener.Start();
  22.   Console.Write(“Array Min and Avg service is now running”
  23.   Console.WriteLine(” on port ” + this.port);
  24.   Console.WriteLine(“Hit <enter> to stop service\n”);
  25.   while (true) {
  26.     try {
  27.       TcpClient tcpClient = await listener.AcceptTcpClientAsync();
  28.       Task t = Process(tcpClient);
  29.       await t;
  30.     }
  31.     catch (Exception ex) {
  32.       Console.WriteLine(ex.Message);
  33.     }
  34.   }
  35. }

This approach restricts the server to listen to requests using only the server’s first assigned IPv4 address. A simpler alternative could allow the server to accept requests sent to any of its addresses by just assigning the member field as this.ipAddress = IPAddress.Any.

Notice the service’s Run method signature uses the async modifier, indicating that in the body of the method some asynchronous method will be called in conjunction with the await keyword. The method returns void rather than the more usual Task because Run is called by the Main method, which, as a special case, does not allow the async modifier. An alternative is to define method Run to return type Task and then call the method as service.Run().Wait.

The service’s Run method instantiates a TcpListener object using the server’s IP address and port number. The listener’s Start method begins monitoring the specified port, waiting for a connection request.

Inside the main processing while loop, a TcpClient object, which you can think of as an intelligent socket, is created and waits for a connection via the AcceptTcpClientAsync method. Prior to the .NET Framework 4.5, you’d have to use BeginAcceptTcpClient and then write custom asynchronous coordination code, which, believe me, is not simple. The .NET Framework 4.5 adds many new methods that, by convention, end with “Async.” These new methods, combined with the async and await keywords, make asynchronous programming much, much easier.

Method Run calls method Process using two statements. An alternative is to use shortcut syntax and call method Process in a single statement: await Process(tcpClient).

To summarize, the service uses TcpListener and TcpClient objects to hide the complexity of raw socket programming, and uses the new AcceptTcpClientAsync method in conjunction with the new async and await keywords to hide the complexity of asynchronous programming. Method Run sets up and coordinates connection activities, and calls method Process to process requests and then a second statement to await on the return Task.

The Service Process and Response Methods

The Process and Response methods of the service object are presented in Figure 4. The Process method’s signature uses the async modifier and returns type Task.

Figure 4 The Demo Service Process and Response Methods

  1. private async Task Process(TcpClient tcpClient)
  2. {
  3.   string clientEndPoint =
  4.     tcpClient.Client.RemoteEndPoint.ToString();
  5.   Console.WriteLine(“Received connection request from “
  6.     + clientEndPoint);
  7.   try {
  8.     NetworkStream networkStream = tcpClient.GetStream();
  9.     StreamReader reader = new StreamReader(networkStream);
  10.     StreamWriter writer = new StreamWriter(networkStream);
  11.     writer.AutoFlush = true;
  12.     while (true) {
  13.       string request = await reader.ReadLineAsync();
  14.       if (request != null) {
  15.         Console.WriteLine(“Received service request: ” + request);
  16.         string response = Response(request);
  17.         Console.WriteLine(“Computed response is: ” + response + “\n”);
  18.         await writer.WriteLineAsync(response);
  19.       }
  20.       else
  21.         break; // Client closed connection
  22.     }
  23.     tcpClient.Close();
  24.   }
  25.   catch (Exception ex) {
  26.     Console.WriteLine(ex.Message);
  27.     if (tcpClient.Connected)
  28.       tcpClient.Close();
  29.   }
  30. }
  31. private static string Response(string request)
  32. {
  33.   string[] pairs = request.Split(‘&’);
  34.   string methodName = pairs[0].Split(‘=’)[1];
  35.   string valueString = pairs[1].Split(‘=’)[1];
  36.   string[] values = valueString.Split(‘ ‘);
  37.   double[] vals = new double[values.Length];
  38.   for (int i = 0; i < values.Length; ++i)
  39.     vals[i] = double.Parse(values[i]);
  40.   string response = “”;
  41.   if (methodName == “average”) response += Average(vals);
  42.   else if (methodName == “minimum”) response += Minimum(vals);
  43.   else response += “BAD methodName: ” + methodName;
  44.   int delay = ((int)vals[0]) * 1000; // Dummy delay
  45.   System.Threading.Thread.Sleep(delay);
  46.   return response;
  47. }

One of the advantages of using low-level sockets instead of Windows Communication Foundation (WCF) is that you can easily insert diagnostic WriteLine statements anywhere you choose. In the demo, I replaced clientEndPoint with the dummy IP address value 123.45.678.999 for security reasons.

The three key lines in method Process are:

  1. string request = await reader.ReadLineAsync();
  2. string response = Response(request);
  3. await writer.WriteLineAsync(response);

You can interpret the first statement to mean, “read a line of the request asynchronously, allowing other statements to execute if necessary.” Once the request string is obtained, it’s passed to the Response helper. Then the response is sent back to the requesting client asynchronously.

The server is using a read-request, write-response cycle. It’s simple, but there are several caveats of which you should be aware. If the server reads without writing, it can’t detect a half-open situation. If the server writes without reading (for example, responding with a large amount of data), it could deadlock with the client. A read-write design is acceptable for simple in-house services but shouldn’t be used for services that are critical or public-facing.

The Response method accepts the request string, parses the request and computes a response string. A simultaneous strength and weakness of a socket-based service is that you must craft some sort of custom protocol. In this case, requests are assumed to look like:

method=average&data=1.1 2.2 3.3&eor

In other words, the service expects the literal “method=” followed by the string “average” or “minimum,” then an ampersand character (“&”) followed by the literal “data=”. The actual input data must be in space-delimited form. The request is terminated by an “&” followed by the literal “eor,” which stands for end-of-request. A disadvantage of socket-based services compared to WCF is that serializing complex parameter types can be a bit tricky sometimes.

In this demo example, the service response is simple, just a string representation of the average or minimum of an array of numeric values. In many custom client-server situations, you’ll have to design some protocol for the service response. For example, instead of sending a response just as “4.00,” you might want to send the response as “average=4.00.”

Method Process uses a relatively crude approach to close a connection if an Exception occurs. An alternative is to use the C# using statement (which will automatically close any connection) and remove the explicit call to method Close.

Helper methods Average and Minimum are defined as:

  1. private static double Average(double[] vals)
  2. {
  3.   double sum = 0.0;
  4.   for (int i = 0; i < vals.Length; ++i)
  5.     sum += vals[i];
  6.   return sum / vals.Length;
  7. }
  8. private static double Minimum(double[] vals)
  9. {
  10.   double min = vals[0]; ;
  11.   for (int i = 0; i < vals.Length; ++i)
  12.     if (vals[i] < min) min = vals[i];
  13.   return min;
  14. }

In most situations, if you’re using a program structure similar to the demo service, your helper methods at this point would connect to some data source and fetch some data. An advantage of low-level services is that you have greater control over your data-access approach. For example, if you’re getting data from SQL, you can use classic ADO.NET,  the Entity Framework or any other data access method.

A disadvantage of a low-level approach is you must explicitly determine how to handle errors in your system. Here, if the demo service is unable to satisfactorily parse the request string, instead of returning a valid response (as a string), the service returns an error message. Based on my experience, there are very few general principles on which to rely. Each service requires custom error handling.

Notice the Response method has a dummy delay:

  1. int delay = ((int)vals[0]) * 1000;
  2. System.Threading.Thread.Sleep(delay);

This response delay, arbitrarily based on the first numeric value of the request, was inserted to slow the service down so that the WinForm and Web application clients could demonstrate UI responsiveness while waiting for a response.

The WinForm Application Demo Client

To create the WinForm client shown in Figure 1, I launched Visual Studio 2012 and created a new C# WinForm application named DemoFormClient. Note that, by default, Visual Studio modularizes a WinForm application into several files that separate the UI code from the logic code. For the code download that accompanies this article, I refactored the modularized Visual Studio code into a single source code file. You can compile the application by launching a Visual Studio command shell (which knows where the C# compiler is), and executing the command: csc.exe /target:winexe DemoFormClient.cs.

Using the Visual Studio design tools, I added a ComboBox control, a TextBox control, two Button controls and a ListBox control, along with four Label controls. For the ComboBox control, I added strings “average” and “minimum” to the control’s Items collection property. I changed the Text properties of button1 and button2 to Send Async and Say Hello, respectively. Then, in design view, I double-clicked on the button1 and button2 controls to register their event handlers. I edited the click handlers as shown inFigure 5.

Figure 5 WinForm Demo Client Button Click Handlers

  1. private async void button1_Click(object sender, EventArgs e)
  2. {
  3.   try {
  4.     string server = “mymachine.network.microsoft.com”;
  5.     int port = 50000;
  6.     string method = (string)comboBox1.SelectedItem;
  7.     string data = textBox1.Text;
  8.     Task<string> tsResponse =
  9.       SendRequest(server, port, method, data);
  10.     listBox1.Items.Add(“Sent request, waiting for response”);
  11.     await tsResponse;
  12.     double dResponse = double.Parse(tsResponse.Result);
  13.     listBox1.Items.Add(“Received response: ” +
  14.      dResponse.ToString(“F2”));
  15.   }
  16.   catch (Exception ex) {
  17.     listBox1.Items.Add(ex.Message);
  18.   }
  19. }
  20. private void button2_Click(object sender, EventArgs e)
  21. {
  22.   listBox1.Items.Add(“Hello”);
  23. }

Notice the signature of the button1 control’s click handler was changed to include the async modifier. The handler sets up a hardcoded server machine name as a string and port number. When using low-level socket-based services, there’s no automatic discovery mechanism and so clients must have access to the server name or IP address and port information.

The key lines of code are:

  1. Task<string> tsResponse = SendRequest(server, port, method, data);
  2. // Perform some actions here if necessary
  3. await tsResponse;
  4. double dResponse = double.Parse(tsResponse.Result);

SendRequest is a program-defined asynchronous method. The call can be loosely interpreted as “send an asynchronous request that will return a string, and when finished continue execution at the statement ‘await tsResponse,’ which occurs later.” This allows the application to perform other actions while waiting for the response. Because the response is encapsulated in a Task, the actual string result must be extracted using the Result property. That string result is converted to type double so that it can be formatted nicely to two decimal places.

An alternative calling approach is:

  1. string sResponse = await SendRequest(server, port, method, data);
  2. double dResponse = double.Parse(sResponse);
  3. listBox1.Items.Add(“Received response: ” + dResponse.ToString(“F2”));

Here, the await keyword is placed in-line with the asynchronous call to SendRequest. This simplifies the calling code a bit and also allows the return string to be fetched without a call to Task.Result. The choice of using an inline await call or using a separate-statement await call will vary from situation to situation, but as a general rule of thumb, it’s better to avoid the explicit use of a Task object’s Result property.

Most of the asynchronous work is performed in the Send­Request method, which is listed in Figure 6. Because SendRequest is asynchronous, it might better be named SendRequestAsync or MySendRequestAsync.

Figure 6 WinForm Demo Client SendRequest Method

  1. private static async Task<string> SendRequest(string server,
  2.   int port, string method, string data)
  3. {
  4.   try {
  5.     IPAddress ipAddress = null;
  6.     IPHostEntry ipHostInfo = Dns.GetHostEntry(server);
  7.     for (int i = 0; i < ipHostInfo.AddressList.Length; ++i) {
  8.       if (ipHostInfo.AddressList[i].AddressFamily ==
  9.         AddressFamily.InterNetwork)
  10.       {
  11.         ipAddress = ipHostInfo.AddressList[i];
  12.         break;
  13.       }
  14.     }
  15.     if (ipAddress == null)
  16.       throw new Exception(“No IPv4 address for server”);
  17.     TcpClient client = new TcpClient();
  18.     await client.ConnectAsync(ipAddress, port); // Connect
  19.     NetworkStream networkStream = client.GetStream();
  20.     StreamWriter writer = new StreamWriter(networkStream);
  21.     StreamReader reader = new StreamReader(networkStream);
  22.     writer.AutoFlush = true;
  23.     string requestData = “method=” + method + “&” + “data=” +
  24.       data + “&eor”; // ‘End-of-request’
  25.     await writer.WriteLineAsync(requestData);
  26.     string response = await reader.ReadLineAsync();
  27.     client.Close();
  28.     return response;
  29.   }
  30.   catch (Exception ex) {
  31.     return ex.Message;
  32.   }
  33. }

SendRequest accepts a string representing the server name and begins by resolving that name to an IP address using the same code logic that was used in the service class constructor. A simpler alternative is to just pass the name of the server: await client.ConnectAsync(server, port).

After the server’s IP address is determined, a TcpClient intelligent-socket object is instantiated and the object’s Connect­Async method is used to send a connection request to the server. After setting up a network StreamWriter object to send data to the server and a StreamReader object to receive data from the server, a request string is created using the formatting expected by the server. The request is sent and received asynchronously and returned by the method as a string.

The Web Application Demo Client

I created the demo Web application client shown in Figure 1 in two steps. First, I used Visual Studio to create a Web site to host the application, and then I coded the Web application using Notepad. I launched Visual Studio 2012 and created a new C# Empty Web Site named DemoClient at http://localhost/. This set up all the necessary IIS plumbing to host an application and created the physical location associated with the Web site at C:\inetpub\wwwroot\DemoClient\. The process also created a basic configuration file, Web.config, which contains information to allow applications in the site to access async functionality in the .NET Framework 4.5:

<?xml version="1.0"?>
    <compilation debug="false" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />

Next, I launched Notepad with administrative privileges. When creating simple ASP.NET applications, I sometimes prefer using Notepad instead of Visual Studio so I can keep all application code in a single .aspx file, rather than generating multiple files and unwanted example code. I saved the empty file as DemoWeb­Client.aspx at C:\inetpub\wwwroot\DemoClient.

The overall structure of the Web application is shown in Figure 7.

Figure 7 Web Application Demo Client Structure

  1. <%@ Page Language=”C#” Async=”true” AutoEventWireup=”true”%>
  2. <%@ Import Namespace=”System.Threading.Tasks” %>
  3. <%@ Import Namespace=”System.Net” %>
  4. <%@ Import Namespace=”System.Net.Sockets” %>
  5. <%@ Import Namespace=”System.IO” %>
  6. <script runat=”server” language=”C#”>
  7.   private static async Task<string> SendRequest(string server,
  8.   private async void Button1_Click(object sender, System.EventArgs e) { . . }
  9. </script>
  10. <head>
  11.   <title>Demo</title>
  12. </head>
  13. <body>
  14.   <form id=”form1″ runat=”server”>
  15.   <div>
  16.   <p>Enter service method:
  17.     <asp:TextBox ID=”TextBox1″ runat=”server”></asp:TextBox></p>
  18.   <p>Enter data:
  19.     <asp:TextBox ID=”TextBox2″ runat=”server”></asp:TextBox></p>
  20.   <p><asp:Button Text=”Send Request” id=”Button1″
  21.     runat=”server” OnClick=”Button1_Click”> </asp:Button> </p>
  22.   <p>Response:
  23.     <asp:TextBox ID=”TextBox3″ runat=”server”></asp:TextBox></p>
  24.   <p>Dummy responsive control:
  25.     <asp:TextBox ID=”TextBox4″ runat=”server”></asp:TextBox></p>
  26.   </div>
  27.   </form>
  28. </body>
  29. </html>

At the top of the page I added Import statements to bring the relevant .NET namespaces into scope, and a Page directive that includes the Async=true attribute.

The C# script region contains two methods, SendRequest and Button1_Click. The application page body has two TextBox controls and one Button control for input, an output TextBox control to hold the service response, and a dummy, unused TextBox control to demonstrate UI responsiveness while the application waits for the service to respond to a request.

The code for the Web application’s SendRequest method is exactly the same as the code in the WinForm application’s Send­Request. The code for the Web application’s Button1_Click handler differs only slightly from the WinForm’s button1_Click handler to accommodate the different UI:

  1. try {
  2.   string server = “mymachine.network.microsoft.com”;
  3.   int port = 50000;
  4.   string method = TextBox1.Text;
  5.   string data = TextBox2.Text;
  6.   string sResponse = await SendRequest(server, port, method, data);
  7.   double dResponse = double.Parse(sResponse);
  8.   TextBox3.Text = dResponse.ToString(“F2”);
  9. }
  10. catch (Exception ex) {
  11.   TextBox3.Text = ex.Message;
  12. }

Even though the code for the Web application is essentially the same as the code for the WinForm application, the calling mechanism is quite a bit different. When a user makes a request using the WinForm, the WinForm issues the call directly to the service and the service responds directly to the WinForm. When a user makes a request from the Web application, the Web application sends the request information to the Web server that’s hosting the application, the Web server makes the call to the service, the service responds to the Web server, the Web server constructs a response page that includes the response and the response page is sent back to the client browser.

Wrapping Up

So, when should you consider using asynchronous TCP sockets instead of WCF? Roughly 10 years ago, before the creation of WCF and its predecessor technology ASP.NET Web Services, if you wanted to create a client-server system, using sockets was often the most logical option. The introduction of WCF was a big advance, but because of the huge number of scenarios WCF is designed to handle, using it for simple client-server systems might be overkill in some situations. Although the latest version of WCF is easier to configure than previous versions, it can still be tricky to work with WCF.

For situations where the client and server are on different networks, making security a major consideration, I always use WCF. But for many client-server systems where client and server are located on a single secure enterprise network, I often prefer using TCP sockets.

A relatively new approach for implementing client-server systems is to use the ASP.NET Web API framework for HTTP-based services combined with the ASP.NET SignalR library for asynchronous methods. This approach, in many cases, is simpler to implement than using WCF and avoids many of the low-level details involved with a socket approach.

Dr. James McCaffrey works for Microsoft Research in Redmond, Wash. He has worked on several Microsoft products including Internet Explorer and Bing. He can be reached at jammc@microsoft.com.

Thanks to the following technical experts for their advice and for reviewing this article: Piali Choudhury (MS Research), Stephen Cleary (consultant), Adam Eversole (MS Research) Lynn Powers (MS Research) and Stephen Toub (Microsoft)

[.NetWorld] Understanding ASP.NET MVC Filters and Attributes

P.NET MVC provides a simple way to inject your piece of code or logic either before or after an action is executed. This is achieved by decorating the controllers or actions with ASP.NET MVC attributes or custom attributes. An attribute or custom attribute implements the ASP.NET MVC filters(filter interface) and can contain your piece of code or logic. You can make your own custom filters or attributes either by implementing ASP.NET MVC filter interface or by inheriting and overriding methods of ASP.NET MVC filter attribute class if available.

Typically, Filters are used to perform the following common functionalities in your ASP.NET MVC application.

  1. Custom Authentication
  2. Custom Authorization(User based or Role based)
  3. Error handling or logging
  4. User Activity Logging
  5. Data Caching
  6. Data Compression

Types of Filters

The ASP.NET MVC framework provides five types of filters.

  1. Authentication filters (New in ASP.NET MVC5)
  2. Authorization filters
  3. Action filters
  4. Result filters
  5. Exception filters

Authentication Filters

This filter is introduced with ASP.NET MVC5. The IAuthenticationFilter interface is used to create CustomAuthentication filter. The definition of this interface is given below-

  1. public interface IAuthenticationFilter
  2. {
  3. void OnAuthentication(AuthenticationContext filterContext);
  4. void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext);
  5. }

You can create your CustomAuthentication filter attribute by implementing IAuthenticationFilter as shown below-

  1. public class CustomAuthenticationAttribute : ActionFilterAttribute, IAuthenticationFilter
  2. {
  3. public void OnAuthentication(AuthenticationContext filterContext)
  4. {
  5. //Logic for authenticating a user
  6. }
  7. //Runs after the OnAuthentication method
  8. public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
  9. {
  10. //TODO: Additional tasks on the request
  11. }
  12. }

Authorization Filters

The ASP.NET MVC Authorize filter attribute implements the IAuthorizationFilter interface. The definition of this interface is given below-

  1. public interface IAuthorizationFilter
  2. {
  3. void OnAuthorization(AuthorizationContext filterContext);
  4. }

The AuthorizeAttribute class provides the following methods to override in the CustomAuthorize attribute class.

  1. public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter
  2. {
  3. protected virtual bool AuthorizeCore(HttpContextBase httpContext);
  4. protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext);
  5. public virtual void OnAuthorization(AuthorizationContext filterContext);
  6. protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext);
  7. }

In this way you can make your CustomAuthorize filter attribute either by implementing IAuthorizationFilter interface or by inheriting and overriding above methods of AuthorizeAttribute class.

Action Filters

Action filters are executed before or after an action is executed. The IActionFilter interface is used to create an Action Filter which provides two methods OnActionExecuting and OnActionExecuted which will be executed before or after an action is executed respectively.

  1. public interface IActionFilter
  2. {
  3. void OnActionExecuting(ActionExecutingContext filterContext);
  4. void OnActionExecuted(ActionExecutedContext filterContext);
  5. }

Result Filters

Result filters are executed before or after generating the result for an action. The Action Result type can be ViewResult, PartialViewResult, RedirectToRouteResult, RedirectResult, ContentResult, JsonResult, FileResult and EmptyResult which derives from the ActionResult class. Result filters are called after the Action filters. The IResultFilter interface is used to create an Result Filter which provides two methods OnResultExecuting and OnResultExecuted which will be executed before or after generating the result for an action respectively.

  1. public interface IResultFilter
  2. {
  3. void OnResultExecuted(ResultExecutedContext filterContext);
  4. void OnResultExecuting(ResultExecutingContext filterContext);
  5. }

Exception Filters

Exception filters are executed when exception occurs during the actions execution or filters execution. The IExceptionFilter interface is used to create an Exception Filter which provides OnException method which will be executed when exception occurs during the actions execution or filters execution.

  1. public interface IExceptionFilter
  2. {
  3. void OnException(ExceptionContext filterContext);
  4. }

ASP.NET MVC HandleErrorAttribute filter is an Exception filter which implements IExceptionFilter. When HandleErrorAttribute filter receives the exception it returns an Error view located in the Views/Shared folder of your ASP.NET MVC application.

Order of Filter Execution

All ASP.NET MVC filter are executed in an order. The correct order of execution is given below:

  1. Authentication filters
  2. Authorization filters
  3. Action filters
  4. Result filters

Configuring Filters

You can configure your own custom filter into your application at following three levels:

  1. Global level

    By registering your filter into Application_Start event of Global.asax.cs file with the help of FilterConfig class.

    1. protected void Application_Start()
    2. {
    3. FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    4. }
  2. Controller level

    By putting your filter on the top of the controller name as shown below-

    1. [Authorize(Roles=”Admin”)]
    2. public class AdminController : Controller
    3. {
    4. //
    5. }
  3. Action level

    By putting your filter on the top of the action name as shown below-

    1. public class UserController : Controller
    2. {
    3. [Authorize(Users=”User1,User2″)]
    4. public ActionResult LinkLogin(string provider)
    5. {
    6. // TODO:
    7. return View();
    8. }
    9. }

[Technology] Phương pháp in sinh học mới giúp tạo ra mô chứa mạng lưới mạch máu

in-mô-3d. ​

Mới đây, một nhóm nghiên cứu đến từ Viện sinh học Wyss thuộc đại học Havard đã giới thiệu một phương pháp in sinh học mới cho phép tạo ra các  có cấu trúc mạch máu và nhiều loại tế bàokhác nhau. Thành tựu này đánh dấu một bước tiến quan trọng hướng đến việc tạo ra các mô sống với đầy đủ chức năng trong phòng thí nghiệm.

Mặc dù công nghệ in 3D từng được sử dụng để tạo ra mô người, nhưng các nhà nghiên cứu vẫn gặp nhiều khó khăn trong việc tái tạo các lớp mô mỏng. Những nổ lực trước đây nhằm tạo ra các lớp mô dày hơn với kích thước bằng 1/3 một đồng xu vẫn gặp phải nhiều khó khăn do các tế bào bên trong thiếu oxy và dưỡng chất đồng thời tế bào không có cách nào để thải chất bã. Kết quả là các lớp mô bị thiếu khí và chết.

3 loại mực tương ứng với các màu xanh, lục và đỏ được sử dụng để “in 3D” các mô.

Để giải quyết vấn đề trên, các nhà nghiên cứu tại viện Wyss đã sử dụng 3 loại mực in sinh học được phát triển đặc biệt với các tính chất vay mượn từ các mô sống thật sự. Loại mực đầu tiên sử dụng ma trận ngoại bào, giúp liên kết các tế bào với nhau để hình thành mô. Loại mực thứ 2 sử dụng hỗn hợp ma trận ngoại bào và các tế bào sống. Loại mực thứ 3 được thiết kế để làm tan chảy lạnh. Điều này có nghĩa một khi nhóm nghiên cứu đã tạo thành công mạng lưới tế bào, nó sẽ được làm lạnh, tan chảy và sau cùng được hút ra khỏi mô, để lại một mạng lưới gồm các ống rỗng được hình thành theo cấu trúc và đây cũng là đường dẫn cho các mạch máu.

Cấu trúc trên mô phỏng một đặc tính cơ bản của mô sống, trong đó tế bào bên trong được duy trì bởi một mạng lưới gồm các mạch máu nhỏ, vách mỏng, cung cấp oxy và dưỡng chất đồng thời cũng đóng vai trò loại bỏ chất thải. Nhóm nghiên cứu đã thử nghiệm mô phỏng và sử dụng một mô hình để tái tạo các mô được in theo nhiều cấu trúc và sau đó tạo ra một cấu trúc mạch máu phức tạp từ 3 loại mực. Theo các nhà nghiên cứu thì đây là một cấu trúc có độ phức tạp rất gần với mô người.

Giáo sư Don Ingber – giám đốc viện Wyss cho biết: “Các kỹ sư tái tạo mô vẫn đang chờ đợi một phương pháp như vậy. Khả năng định hình mạng lưới mạch máu chức năng trong các mô 3D trước khi chúng được cấy ghép không chỉ cho phép tái tạo các mô dày hơn mà còn tăng khả năng liên kết phẫu thuật giữa các mạng mạch máu nhân tạo và mạch máu tự nhiên để nhanh chóng bơm máu vào các mô được cấy ghép, tăng tỉ lệ sống sót cho mô.”

Kế hoạch trước mắt của nhóm nghiên cứu đối với công nghệ trên là tập trung vào việc tạo ra các mô 3D gần với mô sống nhất để có thể sử dụng trong việc kiểm tra độ an toàn và tính hiệu quả của dược phẩm. Nghiên cứu của viện Wyss đã được đăng tải trên tạp chí Advanced Materials số ra tháng này.

[Discovery] Đại học California khai thác năng lượng sóng bằng hệ thống “thảm đáy biển”

seafloor_carpet. ​

Rất nhiều tổ chức trên thế giới đang tìm kiếm những phương pháp khai thác năng lượng của sóng biển làm năng lượng tái tạo. Tuy nhiên, chưa tổ chức nào lại áp dụng phương pháp khai thác từ đáy biển như đại học California tại Berkeley (UC Berkeley). Mới đây, họ đã phát triển một hệ thống có tên gọi “thảm đáy biển” lấy ý tưởng từ lớp bùn đáy biển nhằm khai thác tiềm năng năng lượng từ những con sóng.

Bùn đáy biển được biết đến với khả năng hấp thu chấn động của những con sóng dưới đại dương. Khi một cơn bão mạnh tấn công vịnh Mexico, các ngư dân tại đây biết rằng đáy đại dương phủ đầy bùn sẽ đóng vai trò như một bề mặt phụ, mềm hơn giúp giảm tác động của sóng và cầm chân cơn bão.

Lấy ý tưởng từ hiện tượng này, nhóm nghiên cứu đến từ UC Berkeley đã nghĩ ra một hệ thống trong đó năng lượng của sóng không chỉ được hấp thu mà còn được chuyển đổi thành năng lượng hữu ích.


Hệ thống bao gồm một tấm thảm cao su lớn được đặt bên trên các bộ truyền động thủy lực, xy-lanh và máy bơm để tiếp nhận chuyển động của các cơn sóng tới. Khi di chuyển lên xuống, tấm thảm tạo ra áp lực nước trong các xy-lanh và áp lực này được dẫn ngược vào bờ để chuyển đổi thành năng lượng hữu ích.

Các thử nghiệm được thực hiện tại UC Berkeley cho thấy tấm thảm có khả năng hấp thu hơn 90%năng lượng sóng. Theo các nhà nghiên cứu, một tấm thảm có diện tích 1 m2 có thể tạo ra đủ năng lượng điện cho 2 ngôi nhà tiêu chuẩn tại Mỹ. Trong khi đó, một tấm thảm 100 m2 sẽ có thể cung cấp năng lượng tương đương một sân bóng đá được bao phủ bởi các tấm pin mặt trời với diện tích 6400 m2.

Reza Alam – phó giáo sư đến từ khoa kỹ thuật cơ học tại UC Berkeley cho biết: “Chúng tôi đã lên kế hoạch thử nghiệm hệ thống này tại biển trong vòng 2 năm tới và hy vọng rằng 10 năm sau hệ thống sẽ sẵn sàng để thương mại hóa.”

Nhóm nghiên cứu cũng nhấn mạnh về độ bền và độ linh hoạt của hệ thống. Được phát triển dựa trên ý tưởng đáy biển, được chế tạo từ các vật liệu dẻo không ăn mòn và nhằm mục đích lắp đặt tại các vùng nước nông ven biển ở độ sâu 18 m, hệ thống có thể chịu được động lượng lớn của các vùng biển động. Nhóm cho biết hệ thống có thể được vận chuyển dễ dàng và thiết kế tháo lắp dạng mô-đun cho phép điều chỉnh tỉ lệ chiều rộng tùy theo môi trường và nhu cầu năng lượng.

Bên cạnh việc mang lại một nguồn năng lượng thay thế, quá trình chuyển đổi còn tạo ra nước biển ở áp suất cao có thể được dùng để khử muối và cung cấp nguồn nước sạch cho người dân tại khu vực duyên hải.

Sau khi thử nghiệm thành công tại phòng thí nghiệm tại Berkeley, nhóm nghiên cứu đã đưa dự án lên trang Experiment để gây quỹ từ cộng đồng nhằm đưa dự án tiến đến giao đoạn tiếp theo. Nếu đạt được mục tiêu, nhóm nghiên cứu sẽ phát triển một nguyên mẫu lớn hơn để kiểm tra hiệu năng và thử nghiệm vật liệu phù hợp dành cho các ứng dụng thực tế ngoài đại dương.

[Discovery] Nghiên cứu về khả năng giữ ấm của gấu trắng Bắc cực mở đường các vật liệu cách nhiệt siêu mỏng

polarinsulation. ​

Khi tìm hiểu về khả năng cách nhiệt tuyệt vời của bộ lông gấu trắng Bắc cực, các nhà nghiên cứu đến từ đại học Namur (VQ Bỉ) và đại học Hassan I (VQ Maroc) đã vừa phát hiện ra rằng sự bức xạ nhiệtđóng vai trò lớn hơn so với sự dẫn nhiệt trong việc giữ ấm cơ thể của các động vật sống ở vùng cực như gấu trắng và chim cánh cụt. Qua đó, phát hiện của họ cũng thay đổi những hiểu biết trước đây về cơ chế giữ ấm của chúng.

Những nghiên cứu trước đây tin rằng lông vũ và lông mao giúp các động vật sống ở vùng cực như gấu trắng và chim cánh cụt giữ ấm bằng cách giữ một lớp khí để làm chậm quá trình dẫn nhiệt và thất thoát nhiệt từ cơ thể. Tuy nhiên, nhà khoa học sinh học lượng tử ánh sáng Priscilla Simonis và nhóm của cô đã phát hiện ra rằng nhiệt thất thoát được phân tách bởi không khí bị tác động nhiều hơn bởi bức xạ nhiệt thay vì dẫn nhiệt.

Bằng các mô hình máy tính, nhóm nghiên cứu đã cho thấy cách lớp bảo vệ bức xạ – được sử dụng để mô phỏng các sợi lông mao trong bộ lông của gấu trắng, tán xạ ngược nhiệt một cách rất hiệu quả. Tán xạ ngược là sự đổi hướng của năng lượng theo một góc tối đa 90 độ từ nguồn phát. Sự đổi hướng này không chỉ giới hạn ở quang phổ hồng ngoại, hay nhiệt độ mà còn phản chiếu ánh sáng thấy được, giúp động vật ngụy trang trong điều kiện băng tuyết bằng cách khiến lớp lông bao phủ bên ngoài tiệp màu với môi trường, ở đây là màu trắng. Mặc dù có thể thấy được nhưng lông mao của gấu trắng thực chất lại trong suốt. Khi sử dụng càng nhiều lớp bảo vệ bức xạ – ở đây là thêm nhiều lông, lượng nhiệt thất thoát đã giảm đi đáng kể.

Mô hình máy tính bao gồm 2 chiếc máy điều nhiệt nóng và lạnh để mô phỏng cơ thể động vật và môi trường lạnh bên ngoài. 2 nguồn nhiệt được phân tách bởi một túi khí trong đó có chứa các lớp bảo vệ bức xạ. Trong thử nghiệm đầu tiên, nhóm nghiên cứu đã đặt vào khoảng trống giữa 2 máy điều nhiệt các lớp bảo vệ có tên black-body (toàn bộ lông mao màu đen) với khả năng hấp thụ toàn bộ bức xạ nhiệt và ánh sáng. Mục tiêu của họ là quan sát khả năng truyền dẫn nhiệt thông qua không khí.

Trong thử nghiệm tiếp theo, họ thay lớp bảo vệ black-body bằng các lớp grey-body (toàn bộ lông mao màu xám) chắn sáng để giảm tỉ lệ truyền dẫn và phản chiếu ánh sáng. Các lớp bảo vệ này mô phỏng lớp lông mao và lông vũ của động vật tại vùng cực. Họ nhận ra rằng bằng cách tăng hệ số phản xạ của lớp bảo vệ grey-body hay nói đơn giản là thêm vào khoảng trống giữa 2 máy điều nhiệt nhiều lớp bảo vệ hơn, tỉ lệ truyền dẫn nhiệt đã giảm đi đột ngột.

Ảnh phóng to lông tơ của một con công trắng với các lông phụ kéo dài giúp khuếch tán bức xạ nhiệt, giữ ấm cho cơ thể.

Simonis cho biết: “Đặc tính này rất hữu ích đối với động vật, chẳng hạn như động vật có vú và chim chóc sinh sống tại các khu vực băng tuyết.” Phát hiện của Simonis cũng mở ra một câu hỏi rằng tại sao việc chế tạo các vật liệu cách nhiệt vẫn không đạt hiệu quả cao trong khi gấu trắng Bắc cực chỉ với bộ lông dày vài inch lại có thể cách ly cơ thể ở nhiệt độ 37 độ C với nhiệt độ bên ngoài xuống đến – 40 độ C.

“Tại sao chúng ta phải cần đến những tấm bông khoáng hay bông thủy tinh cách nhiệt dày ít nhất 60 cm để cách ly nhiệt độ 20 độ C bên trong từ nhiệt độ – 5 độ C bên ngoài. Tại sao bộ lông của gấu trắng lại hiệu quả hơn so với những gì chúng ta có thể phát triển dành cho ngôi nhà của mình,” Simonis đặt câu hỏi.

Cô gợi ý rằng nghiên cứu trên có thể mang lại một loạt các ứng dụng cho con người và có thể dẫn đến sự phát triển của các loại vật liệu cách nhiệt siêu mỏng mới. Không chỉ được dùng để cách nhiệt cho các tòa nhà, vật liệu còn có thể được dùng trong quần áo ấm, túi ngủ và trang thiết bị sinh tồn.

Nghiên cứu của Simonis cùng các công sự đã vừa được đăng tải trên tạp chí Optics Express.

[Discovery] Đại học Stanford chế tạo thành công điện cực nanosilicon lấy cảm hứng từ cấu trúc hạt quả lựu

Pin_qua_luu. ​

Các nhà khoa học thuộc phòng thí nghiệm gia tốc quốc tế DOE/SLAC và Đại học Stanford đang thử nghiệm loại điện cực bên trong chứa các hạt nano silicon được sắp xếp theo cấu trúc nhóm giống như hạt quả lựu. Thiết kế trên cho phép chế tạo ra loại pin sạc với kích thước nhỏ, nhẹ hơn dành cho xe điện, điện thoại di động và những thiết bị khác.

Mỗi điện cực được thiết kế giống như một quả lựu: các hạt nano silicon được nhóm lại với nhau, mỗi nhóm ngăn cách bởi các lớp màng carbon. Cách thiết kế trên đã khắc phục được các trở ngại hiện tại trong việc sử dụng vật liệu silicon cho pin lithium-ion.

Trong bài phỏng vấn với tạp chí nNature Nanotechnology, Yi Cui, Giáo sư tại đại học Stanford và cũng là người đứng đầu dự án đã chia sẻ: “Trước mắt vẫn còn một số thách thức cần phải vượt qua. Tuy nhiên phương pháp dùng silicon làm điện cực cho phép chế tạo ra những thê hệ pin kích thước nhỏ, trọng lượng nhẹ và thời lượng lớn hơn để có thể áp dụng cho điện thoại di động, máy tính bảng và xe điện trong tương lai.”

Các thử nghiệm đầu tiên cho thấy loại pin sử dụng “điện cực hạt lựu” vẫn hoạt động ở công suất 97% sau 1000 lần sạc. Điều này hoàn toàn thỏa mãn những yêu cầu để được thương mại hóa rộng rãi trong tương lai gần.

Cực dương và cực âm là nơi năng lượng được lưu trữ trong quá trình sạc pin. Các điện cực siliconcó thể chứa lượng năng lượng gấp 10 lần so với các điện cực bằng than chì hiện vẫn đang được sử dụng cho các pin sạc lithium-ion hiện nay. Tuy nhiên trước đây, điện cực silicon không phải là không có khuyết điểm: Các hạt silicon có thể trương phồng lên, vỡ ra và khiến lớp màng carbon gói mỗi nhóm hạt bị vỡ trong quá trình sạc pin. Ngoài ra, chất liệu silicon sẽ phản ứng với chất điện giải và tạo thành lớp chất bẩn đóng bên ngoài điện cực làm giảm hiệu suất làm việc của pin.

Trong suốt 8 năm, nhóm nghiên cứu của giáo sư Cui đã nghiên cứu nhằm khắc phục được nhược điểm trên bằng cách sử dụng các hạt silicon kích thước nano. Những hạt silicon này có kích thước quá nhỏ nên không thể vỡ ra thành các hạt nhỏ hơn được nữa. Ngoài ra, lớp màng carbon bọc bên ngoài có tính đàn hồi cao nên có thể phồng ra và co lại trong quá trình sạc pin.

Dựa trên nghiên cứu của giáo sư Cui, 2 nhà nghiên cứu Nian Liu và Zhenda Lu đã sử dụng kỹ thuậtmàng vi nhũ tương thường được áp dụng cho dầu mỏ, dầu sơn và ngành công nghiệp mỹ phẩm để tạo lớp màng bao bọc cho các hạt nano silicon. Lớp màn trên được hình dung là lớp nhũ tương bao quanh gói hạt bên trong giống như lòng đỏ và lòng trắng trứng gà. Lớp màn nhũ tương chẳng những giúp cho các gói hạt ổn định hơn mà còn cho phép dòng điện di chuyển tốt hơn trong quá trình sạc pin.

Bên cạnh đó, chính nhờ thiết kế thành từng gói mà diện tích tiếp xúc của các hạt silicon với chất điện giải ít hơn, từ đó giúp giảm đáng kể lượng tạp chất sinh ra trong quá trình hoạt động.

Hiện tại, công nghệ trên đã tiến rất gần đến giai đoạn thương mại hóa. Vấn đề duy nhất mà nhóm nghiên cứu cần giải quyết chính là tìm nguồn nguyên liệu nano silicon giá rẻ và đơn giản hóa chu trình sản xuất. Một nguồn nano silicon giá rẻ mà nhóm đang hướng tới sử dụng chính là vỏ trấu: một loại nguyên liệu bỏ đi sau khi tách hạt gạo bên trong, Hàng triệu tấn trấu được sản xuất mỗi năm và 20% thành phần chứa silicon dioxide mà theo giáo sư Liu, có thể được chuyển đổi dễ dàng thành nano silicon.

Giáo sư Liu chia sẻ: “Chúng tôi thực sự phấn khởi khi nhìn thấy được công trình trong suốt 8 năm qua đã có được thành công. Chúng tôi đã có thể từng bước một giải quyết được các vấn đề trở ngại lúc ban đầu.”

[Discovery] Viện Houston phát triển công nghệ in tế bào giống in mộc bản với tỉ lệ sống gần 100%

blocprinting-1. ​

Các nhà nghiên cứu tại viện Houston đã vừa phát triển một phương pháp giá rẻ để in các tế bào sống với tỉ lệ sống sót gần 100%. Phương pháp in này khá giống với phương pháp in mộc bản của người Trung Quốc cổ và nó cho phép in tế bào trên mọi bề mặt dưới dạng 2 chiều. Trong khi công nghệ in phun hiện nay có thể in các tế bào sống với chi phí lên đến 10.000 USD với tỉ lệ sống sót của tế bào chỉ khoảng 50% thì kỹ thuật mới có thể tạo ra tế bào hàng loạt với mức giá chỉ 1 USD.

Block-Cell-Printing hay BloC là tên công nghệ in mới do viện nghiên cứu Houston phát triển. Do còn nằm trong giai đoạn trứng nước nên BloC có những hạn chế như tốc độ in chậm, tốn nhiều công sức hơn so với công nghệ in phun và chưa thể in 3 chiều. Các nhà nghiên cứu cho biết kỹ thuật hiện tại có thể in các hình mẫu phân giải cao với các tế bào ở tỉ lệ 5 micromet và có thể thực hiện với nhiều loại tế bào khác nhau. Tất cả đều có tỉ lệ sống sót cao. Một tế bào động vật trung bình có đường kính từ 10 đến 20 micromet.

Giáo sư Lidong Qin đến từ viện nghiên cứu liệu pháp Houston cho biết: “Công nghệ in tế bào hiện đang được sử dụng trong nhiều lĩnh vực như thử nghiệm và điều chế dược phẩm, tái tạo mô, chức năng tế bào và giao tiếp giữa tế bào- tế bào. Những thứ như vậy chỉ có thể được thực hiện khi các tế bào còn sống và hoạt động. 50 đến 80% là tỉ lệ sống sót thông thường của các tế bào khi rời ngòi phun của máy in. Nếu so sánh, chúng tôi đạt tỉ lệ gần 100% với quy trình in BloC. Chúng tôi nhận thấy các công nghệ hiện tại không đủ khả năng đáp ứng. Công nghệ in phun khiến cho một số lượng lớn tế bào bị tổn thương và chết. Chúng tôi mong muốn phát minh một công cụ để giúp các nhà nghiên cứu thu được các tế bào hàng loạt mà chúng vẫn còn sống và vẫn có thể hoạt động hoàn toàn.”

Kỹ thuật in BloC sử dụng vật lý vi lỏng để dẫn các tế bào sống vào một loạt các khe hình chữ J nằm trên một khuôn silicon. Các tế bào chảy theo cột và lấp đầy các khe trống này. Khi một khe đã đầy, chúng tiếp tục chảy lên các khe tiếp theo, tạo ra một rãnh chứa các tế bào. Các đường rãnh tế bào trên bề mặt khuôn được bố trí theo một mạng lưới định sẵn trong quá trình sản xuất. Một khi đã được nạp đầy các tế bào, khuôn silicon sau đó có thể được sử dụng như một con dấu cao su. Các tế bào có thể được in lên một bề mặt, chẳng hạn như một chất nuôi cấy trung gian.

Hiện tại, Qin đã bắt đầu thử nghiệm BloC bằng việc in một lưới các tế bào não đồng thời tiến hành xem xét sự phát triển của các tế bào ung thư. “Mạng lưới tế bào mà chúng tôi tạo ra có thể rất hữu ích trong các nghiên cứu dẫn truyền tín hiệu thần kinh và tái tạo sợi trục thần kinh. Những nghiên cứu này sẽ giúp hiểu rõ hơn về bệnh Alzheimer và các chứng thoái hóa thần kinh khác,” Qi nói.