Il presente articolo è stato tradotto automaticamente.

ASP.NET

Utilizzo di framework con più codice con un'unica struttura ASP.NET

Jeff Fritz

Nel 2001, quando Microsoft ha introdotto il Microsoft .NET Framework e, con esso, una nuova tecnologia chiamata ASP.NET, sviluppatori Web abbracciarono per la costruzione di siti utilizzando un framework basato su moduli. Questo quadro, noto come Web Form, superato la prova del tempo per otto anni, con miglioramenti e modifiche per supportare un ambiente Web in continua evoluzione. Creazione di un'applicazione Web in quel periodo era una scelta semplice, con una finestra di dialogo nuovo progetto che ha presentato quattro opzioni di ASP.NET , come mostrato Figura 1. La maggior parte di noi ignorati i progetti di sito Web per Mobile ASP.NET e libreria di controlli Web e costruito solo progetti di applicazione Web ASP.NET . Se avete bisogno di servizi Web, vorrei aggiungere un servizio basato su SOAP a un sito Web esistente con un file. asmx.

The Original New Project ASP.NET Choices in Visual C#
Figura 1 l'originale nuovo progetto ASP.NET scelte in Visual c#

All'inizio del 2009, il paesaggio ASP.NET cambiò drasticamente con l'introduzione del Model-View-Controller (MVC). Con la promessa di non più viewstate, pagina eventi del ciclo di vita o eventi di postback per gestire, gli sviluppatori sono accorsi al nuovo quadro. Sono stato uno di loro, incuriosito dalle potenzialità di questa tecnologia Web più verificabile. Abbiamo dovuto trovare il modo per giustificare ai nostri responsabili e centri di costo del bilancio per la commutazione applicazioni MVC, e molti sviluppatori hanno lavorato attraverso i passi per ottenere contenuti MVC presentato nella stessa applicazione come applicazione Web Form esistente. Cose ha lavorato molto bene con MVC per diversi anni, e quindi il Web cresciuto un po '. ASP.NET necessari per evolvere ancora.

Nel 2012, Microsoft ha consegnato due nuovi quadri di aggiungere per il toolkit ASP.NET : Web API e SignalR. Entrambi questi quadri portare qualcosa di speciale per l'ambiente, e ognuno è unico a modo suo:

  • Web API fornisce un'esperienza di MVC-come per gli sviluppatori di contenuti destinati alla interpretazione di macchina. Non non c'è alcuna interfaccia utente, e le transazioni avvengono in maniera riposante. Tipi di contenuto vengono negoziati e Web API può formattare automaticamente il contenuto come JSON o XML, basato sulle intestazioni HTTP presentate a un endpoint Web API.
  • SignalR è il nuovo modello di recapito "Real-Time Web" da Microsoft. Questa tecnologia si apre il canale di comunicazione client-server per consentire comunicazioni immediate, ricche dal server al client. Il modello di distribuzione di contenuti in SignalR inverte le nostre aspettative normali, come il server chiama il client per interagire con il contenuto.

Si consideri il trade-off già visto tra MVC e Web Form con quelli di Web API e MVC, come mostrato Figura 2.

Figura 2 benefici di ogni quadro componente ASP.NET

Framework Produttività InkPresenter interfaccia utente Tempo reale
Web Form    
MVC    
Web API    
SignalR      

Produttività comporta caratteristiche che consentono di sviluppare e distribuire rapidamente una soluzione. Il controllo è nella misura in cui si possono influenzare i bit di trasmissione attraverso la rete agli utenti connessi. Interfaccia utente indica se è possibile utilizzare il quadro per fornire un'interfaccia utente completa. Infine, tempo reale suggerisce quanto bene il quadro presenta i contenuti in modo tempestivo che potrebbe essere percepito come un aggiornamento immediato.

Ora, nel 2013, quando apro la mia copia di Visual Studio e tenta di avviare un progetto ASP.NET , sono affrontato con le finestre di dialogo mostrati Figura 3 e Figura 4.

New Web Project in Visual Studio 2012
Figura 3 nuovo progetto Web in Visual Studio 2012

New Project Template Dialog in Visual Studio 2012
Figura 4 nuovo progetto modello finestra di dialogo in Visual Studio 2012

Ci sono alcune domande difficili in quelle finestre. Che tipo di progetto devo cominciare? Modello di ciò che sta andando a me più vicino alla mia soluzione, più veloce? E cosa succede se si desidera includere alcuni componenti di ogni modello? Posso costruire un'applicazione mobile con alcuni controlli server e un'API Web?

E ' necessario scegliere un solo approccio?

E ' necessario scegliere un solo approccio? La risposta breve è no, non devi selezionare solo uno di questi quadri per costruire un'applicazione Web. Ci sono tecniche disponibili che consentono di utilizzare insieme Web Form e MVC, e contrariamente alle finestre di dialogo presentate, Web API e SignalR può essere facilmente aggiunto come funzionalità a un'applicazione Web. Ricordate, tutti i contenuti ASP.NET sono reso attraverso una serie di gestori HTTP e moduli http. Fintanto che i gestori corretti e i moduli si fa riferimento, è possibile costruire una soluzione con uno qualsiasi di questi quadri.

Questo è il cuore del concetto "One ASP.NET": Don' t scegliere solo uno di questi quadri — compilare la soluzione con le parti di ciascuno che meglio si adattano alle vostre esigenze. Hai un numero di scelte; non limitatevi a uno solo.

Così si può vedere questo in azione, ho intenzione di mettere insieme una piccola applicazione Web che avrà un layout unificato, una schermata di ricerca e una schermata di creazione per un elenco dei prodotti. La schermata di ricerca sarà alimentato da Web Forms e Web API e visualizza gli aggiornamenti live da SignalR. La schermata di creazione verrà generata automaticamente da modelli MVC. Inoltre ho intenzione di rendere il Web Form guardare grande utilizzando una libreria di controlli di terze parti, Telerik RadControls per ASP.NET AJAX. Una versione di prova di questi controlli è disponibile presso bit.ly/15o2Oab.

Impostare il progetto di esempio e Layout condiviso

Per iniziare, è necessario creare un progetto utilizzando la finestra di dialogo mostrata Figura 3. Mentre ho potuto scegliere un vuoto o applicazioni Web Form­cazione, la soluzione più completa per scegliere è l'applicazione MVC. A partire da un progetto MVC è un'ottima scelta perché ottenete tutti gli utensili da Visual Studio per configurare i tuoi modelli, visualizzazioni e controller, come pure la possibilità di aggiungere oggetti Web Form in un punto qualsiasi nella struttura del file di progetto. È possibile aggiungere il MVC utensileria indietro in un'applicazione Web esistente­cazione modificando alcuni contenuti XML nel file csproj. Questo processo può essere automatizzato installando il pacchetto NuGet chiamato AddMvc3ToWebForms.

Per configurare i controlli Telerik per uso in questo progetto, è necessario fare alcuni hacking in Web. config per aggiungere i gestori HTTP e HttpModules che normalmente sarebbe essere configurato in un progetto di Telerik RadControls standard. In primo luogo, io aggiungo un paio di righe per definire l'AJAX Telerik controlli pelle UI:

<add key="Telerik.Skin" value="WebBlue" />
</appSettings>

Successivamente, aggiungerò il prefisso di tag Telerik:

<add tagPrefix="telerik" namespace="Telerik.Web.UI" assembly="Telerik.Web.UI" />
</controls>

Farò le aggiunte minime necessarie per l'Http Web.config­i gestori per i controlli Telerik:

<add path="Telerik.Web.UI.WebResource.axd" type="Telerik.Web.UI.WebResource"
    verb="*" validate="false" />
</httpHandlers>

E, infine, farò le aggiunte ai gestori per i controlli Telerik Web. config:

<system.WebServer>
  <validation validateIntegratedModeConfiguration="false" />
  <handlers>
    <remove name="Telerik_Web_UI_WebResource_axd" />
    <add name="Telerik_Web_UI_WebResource_axd"
      path="Telerik.Web.UI.WebResource.axd"
      type="Telerik.Web.UI.WebResource" verb="*" preCondition="integratedMode" />

Ora voglio creare una pagina di layout per questo progetto, quindi creerò una pagina di Web Form site nelle viste | Cartella condivisa. Per questo layout del sito, voglio aggiungere un logo standard e menù per tutte le pagine. Io aggiungo un logo immagine trascinando semplicemente l'immagine nel mio layout. Quindi, per aggiungere un grande menu CSS per il layout, trascineremo un RadMenu dalla mia casella degli strumenti controlli nella finestra di progettazione, appena sotto l'immagine. Dalla superficie del progettista, rapidamente posso costruire il mio menu facendo clic destro sul controllo menu e selezionando Modifica elementi per ottenere la finestra mostrata Figura 5.

Telerik RadMenu Configuration Window
Figura 5 finestra di configurazione di Telerik RadMenu

Le due voci di menu che voglio mettere a fuoco sono sotto prodotti — ricerca e nuova. Per ciascuno di questi elementi, ho impostato la proprietà NavigateUrl e testo come segue:

<telerik:RadMenuItem Text="Products">
  <Items>
    <telerik:RadMenuItem Text="Search" NavigateUrl="~/Product/Search" />
    <telerik:RadMenuItem Text="New" NavigateUrl="~/Product/New" />
  </Items>
</telerik:RadMenuItem>

Con il menu configurato, ora hanno un problema dove ho definito il mio layout utilizzando Web Forms e si devono ospitare contenuti MVC. Questo non è un problema banale, ma è un problema che può essere risolto.

Colmare il divario — configurazione MVC per utilizzare un Web Master pagina Form

Come la maggior parte di voi, preferisco mantenere le cose semplici. Voglio condividere il mio layout definito per questo progetto tra MVC e Web Form. C'è una tecnica ben documentata ideata da Matt Hawley che viene illustrato come utilizzare una pagina master Web Form con visualizzazioni basate su MVC Razor (bit.ly/ehVY3H). Ho intenzione di utilizzare tale tecnica in questo progetto. Per creare questo ponte, potrai configurare una semplice visualizzazione Web Form chiamata RazorView.aspx che fa riferimento alla pagina master:

<%@ Page Language="C#" AutoEventWireup="true"
  MasterPageFile="~/Views/Shared/Site.Master"
  Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<%@ Import Namespace="System.Web.Mvc" %>
<asp:Content id="bodyContent" runat="server" 
  ContentPlaceHolderID="body">
<% Html.RenderPartial((string)ViewBag._ViewName); %>
</asp:Content>

In ordine per il mio controller MVC utilizzare questa visualizzazione e consentire loro visualizzazioni basate sul rasoio per essere eseguito, è necessario estendere ogni controller per indirizzare opportunamente il contenuto della vista. Questo si realizza attraverso un metodo di estensione che reindirizza il modello, ViewData e TempData opportunamente attraverso RazorView.aspx, come mostrato Figura 6.

Figura 6 il metodo di estensione RazorView per reindirizzare visualizzazioni MVC tramite un Web Master pagina Form

public static ViewResult RazorView(this Controller controller,
  string viewName = null, object model = null)
{
  if (model != null)
    controller.ViewData.Model = model;
  controller.ViewBag._ViewName = !string.IsNullOrEmpty(viewName)
    ?
viewName
    : controller.RouteData.GetRequiredString("action");
  return new ViewResult
  {
    ViewName = "RazorView",
    ViewData = controller.ViewData,
    TempData = controller.TempData
  };
}

Con questo metodo costruito, io posso facilmente indirizzare tutte le azioni di MVC tramite la pagina master. Il passo successivo è quello di impostare il ProductsController affinché i prodotti possono essere creati.

MVC e il creare prodotto schermo

La parte MVC di questa soluzione è un approccio MVC abbastanza standard. Ho definito un oggetto semplice modello chiamato BoardGame nella cartella Models del mio progetto, come mostrato Figura 7.

Figura 7 l'oggetto del gioco da tavolo

public class BoardGame
{
  public int Id { get; set; }
  public string Name { get; set; }
  [DisplayFormat(DataFormatString="$0.00")]
  public decimal Price { get; set; }
  [Display(Name="Number of items in stock"), Range(0,10000)]
  public int NumInStock { get; set; }
}

Successivamente, utilizzando standard MVC stampi in Visual Studio, creare un vuoto ProductController. Io aggiungo un Views | Cartella del prodotto, quindi fare clic destro sulla cartella del prodotto e scegliere Visualizza dal menu Aggiungi. Questa vista sosterrà la creazione di nuovi giochi da tavolo, quindi creerò con le opzioni come mostrato Figura 8.

Creating the “New” View
Figura 8 creando la vista "Nuova"

Grazie alle attrezzature MVC e modelli, non ho bisogno di cambiare una cosa. La vista creata ha le etichette e la convalida e può utilizzare la mia pagina master. Figura 9 viene illustrato come definire la nuova azione nella ProductController.

Figura 9 ProductController Routing attraverso il RazorView

public ActionResult New()
{
  return this.RazorView();
}
[HttpPost]
public ActionResult New(BoardGame newGame)
{
  if (!ModelState.IsValid)
  {
    return this.RazorView();
  }
  newGame.Id = _Products.Count + 1;
  _Products.Add(newGame);
  return Redirect("~/Product/Search");
}

Questa sintassi dovrebbe essere familiare agli sviluppatori MVC, come l'unico cambiamento è quello di restituire una RazorView invece di una vista. L'oggetto _Products è un insieme statico, in sola lettura di fittizi prodotti definiti in questo controller (invece di utilizzare un database in questo esempio):

public static readonly List<BoardGame> _Products = 
  new List<BoardGame>()
{
  new BoardGame() {Id=1, Name="Chess", Price=9.99M},
  new BoardGame() {Id=2, Name="Checkers", Price=7.99M},
  new BoardGame() {Id=3, Name="Battleship", Price=8.99M},
  new BoardGame() {Id=4, Name="Backgammon", Price= 12.99M}
};

Configurare la pagina di ricerca basata su moduli Web

Voglio che i miei utenti di essere in grado di accedere alla pagina di ricerca del prodotto con un URL che non sembra è un URL di Web Form ed è amichevole per la ricerca. Con il rilascio di ASP.NET 2012.2, questo ora può essere configurato facilmente. Basta aprire il file App_Start/RouteConfig.cs e chiamare EnableFriendlyUrls per attivare questa funzionalità:

public static void RegisterRoutes(
    RouteCollection routes)
  {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.EnableFriendlyUrls();
    routes.MapRoute(
      name: "Default",
      url: "{controller}/{action}/{id}",
      defaults: new { controller = "Home", action =
        "Index", id = UrlParameter.Optional }
    );
  }

Con questa linea aggiunta, ASP.NET instraderà richieste per /Product/Search al file fisico residente in /Product/Search.aspx

Avanti, voglio configurare una pagina di ricerca che mostra una griglia di prodotti attuali e i livelli delle scorte. Io creare una cartella del prodotto nel mio progetto e aggiungere un nuovo modulo Web è denominato aspx. In questo file, potrai rimuovere markup tutto tranne la direttiva @Page e impostare il MasterPageFile file site definito in precedenza. Per visualizzare i miei risultati, scelgo il Telerik RadGrid così rapidamente posso configurare e visualizzare i dati di risultato:

<%@ Page Language="C#" AutoEventWireup="true"
  CodeBehind="Search.aspx.cs"
  Inherits="MvcApplication1.Product.Search"
  MasterPageFile="~/Views/Shared/Site.Master" %>
<asp:Content runat="server" id="main" ContentPlaceHolderID="body">
  <telerik:RadGrid ID="searchProducts" runat="server" width="500"
    AllowFilteringByColumn="True" CellSpacing="0" GridLines="None"
    AllowSorting="True">

La griglia renderà automaticamente colonne associate ad esso sul server side e forniscono funzionalità di filtro e ordinamento. Tuttavia, vorrei rendere questo più dinamico. Voglio vedere dei dati forniti e gestiti sul lato client. In questo modello, dati potrebbero essere trasmessa e legati con nessun codice sul lato server in Web Forms. A tale scopo, ho intenzione di aggiungere un Web API che forniscono e svolgere le operazioni sui dati.

Aggiunta di Web API per il Mix

Io uso il progetto standard | Aggiungi nuovo menu per aggiungere un controller API Web denominato ProductController in una cartella denominata "api" nel mio progetto. Questo mi aiuta a mantenere chiare le differenze tra il controller MVC e il controller di API. Questa API è andare a fare una cosa — fornire dati per la mia griglia in formato JSON e supportano le query OData. A tale scopo nel Web API, ho intenzione di scrivere un singolo metodo Get e decorarla con l'attributo Queryable:

[Queryable]
public IQueryable<dynamic> Get(ODataQueryOptions options)
{
  return Controllers.ProductController._Products.Select(b => new
  {
    Id = b.Id,
    Name = b.Name,
    NumInStock = b.NumInStock,
    Price = b.Price.ToString("$0.00")
  }).AsQueryable();
}

Questo codice restituisce la mia collezione di giochi da tavolo oggetti nell'elenco statico con un piccolo pezzo di formattazione. Il metodo con [Queryable] di decorazione e restituendo una raccolta queryable, il framework Web API automaticamente gestirà ed elaborare i comandi di filtro e ordinamento OData. Il metodo deve inoltre essere configurato con il parametro di input ODataQueryOptions al fine di gestire i dati presentati dalla griglia.

Per configurare la griglia su aspx per consumare questa nuova API, è necessario aggiungere alcune impostazioni del client al markup della pagina. In questo controllo griglia, definire il databinding client con un elemento ClientSettings e un'impostazione DataBinding. L'impostazione di DataBinding elenca la posizione dell'API, il tipo di formato di risposta e il nome del controller di query, come pure il formato di query OData. Con queste impostazioni e una definizione delle colonne presenti nella griglia, posso eseguire il progetto e vedere la griglia associata ai dati nell'elenco dei dati, fittizio _Products come Figura 10 illustrato.

Figura 10 Fonte formattazione completa della griglia

<telerik:RadGrid ID="searchProducts" runat="server" width="500"
  AllowFilteringByColumn="True" CellSpacing="0" GridLines="None"
  AllowSorting="True" AutoGenerateColumns="false"
  >
    <ClientSettings AllowColumnsReorder="True"
      ReorderColumnsOnClient="True"
      ClientEvents-OnGridCreated="GridCreated">
      <Scrolling AllowScroll="True" UseStaticHeaders="True"></Scrolling>
      <DataBinding Location="/api" ResponseType="JSON">
        <DataService TableName="Product" Type="OData"  />
      </DataBinding>
    </ClientSettings>
    <MasterTableView ClientDataKeyNames="Id" DataKeyNames="Id">
      <Columns>
        <telerik:GridBoundColumn DataField="Id" HeaderStyle-Width="0"
          ItemStyle-Width="0"></telerik:GridBoundColumn>
        <telerik:GridBoundColumn DataField="Name" HeaderText="Name"
          HeaderStyle-Width="150" ItemStyle-Width="150">
          </telerik:GridBoundColumn>
        <telerik:GridBoundColumn ItemStyle-CssClass="gridPrice"
          DataField="Price"
          HeaderText="Price" ItemStyle-HorizontalAlign="Right">
          </telerik:GridBoundColumn>
        <telerik:GridBoundColumn DataField="NumInStock"
          ItemStyle-CssClass="numInStock"
          HeaderText="# in Stock"></telerik:GridBoundColumn>
      </Columns>
    </MasterTableView>
  </telerik:RadGrid>

Attivando la griglia con i dati in tempo reale

L'ultimo pezzo del puzzle è la possibilità di visualizzare le modifiche in tempo reale dei livelli di magazzino come i prodotti sono spediti e ricevuti. Ho intenzione di aggiungere un hub SignalR per trasmettere gli aggiornamenti e presentare i nuovi valori sulla griglia di ricerca. Per aggiungere SignalR al mio progetto, è necessario eseguire i seguenti due comandi NuGet:

Install-Package -pre Microsoft.AspNet.SignalR.SystemWeb
Install-Package -pre Microsoft.AspNet.SignalR.JS

Questi comandi saranno installare i componenti server ASP.NET per ospitare all'interno del server Web IIS e rendere il client JavaScript librerie disponibili per il Web Form.

La componente lato server SignalR è chiamato un Hub, e miniera definirò aggiungendo una classe denominata StockHub in una cartella denominata mozzi nel mio progetto Web. La StockHub è necessaria per scendere dalla classe Microsoft.AspNet.SignalR.Hub. Ho definito una statica System.Timers.Timer per consentire all'applicazione simulare la modifica dei livelli delle scorte. Per questa simulazione, ogni 2 secondi (quando il gestore dell'evento Elapsed timer attiva), casualmente impostiamo il livello delle scorte del prodotto scelto in modo casuale. Una volta impostato il livello di scorte di prodotto, io sarò notificare ai client tutti collegati tramite l'esecuzione di un metodo sul client chiamato setNewStockLevel, che è indicato nella Figura 11.

Figura 11 il componente lato Server Hub SignalR

public class StockHub : Hub
{
  public static readonly Timer _Timer = new Timer();
  private static readonly Random _Rdm = new Random();
  static StockHub()
  {
    _Timer.Interval = 2000;
    _Timer.Elapsed += _Timer_Elapsed;
    _Timer.Start();
  }
  static void _Timer_Elapsed(object sender, ElapsedEventArgs e)
  {
    var products = ProductController._Products;
    var p = products.Skip(_Rdm.Next(0, products.Count())).First();
    var newStockLevel = p.NumInStock + 
      _Rdm.Next(-1 * p.NumInStock, 100);
    p.NumInStock = newStockLevel;
    var hub = GlobalHost.ConnectionManager.GetHubContext<StockHub>();
    hub.Clients.All.setNewStockLevel(p.Id, newStockLevel);
  }
}

Per i dati di questo hub siano accessibili dal server, è necessario aggiungere una linea di RouteConfig che indica la presenza dell'hub. Chiamando rotte.MapHubs il metodo RegisterRoutes del RouteConfig, completare la configurazione lato server di SignalR.

Successivamente, la griglia ha bisogno di ascoltare questi eventi dal server. A tale scopo, è necessario aggiungere alcuni riferimenti di JavaScript per la libreria client SignalR installato da NuGet e il codice generato dal comando MapHubs. Il servizio SignalR si connette ed espone il metodo di setNewStockLevel sul client utilizzando il codice mostrato Figura 12.

Figura 12 SignalR codice Client per attivare la griglia

<script src="/Scripts/jquery.signalR-1.0.0-rc2.min.js"></script>
<script src="/signalr/hubs"></script>
<script type="text/javascript">
  var grid;
  $().ready(function() {
      var stockWatcher = $.connection.stockHub;
      stockWatcher.client.setNewStockLevel = function(id, newValue) {
        var row = GetRow(id);
        var orgColor = row.css("background-color");
        row.find(".
numInStock").animate({
          backgroundColor: "#FFEFD5"
        }, 1000, "swing", function () {
          row.find(".
numInStock").html(newValue).animate({
            backgroundColor: orgColor
          }, 1000)
        });
      };
      $.connection.hub.start();
  })
</script>

Nel gestore dell'evento ready jQuery, stabilisco un riferimento chiamato stockWatcher per la StockHub utilizzando il $. connection.stockHub sintassi. Definire quindi il metodo setNewStockLevel sulla proprietà client della stockWatcher. Questo metodo utilizza alcuni altri metodi di supporto JavaScript per attraversare la griglia, individuare la riga con il prodotto appropriato e modificare il livello delle scorte con un animazione fantasia colore fornito da jQuery UI, come mostrato Figura 13.

The Search Interface with Grid Generated by Web API and Maintained by SignalR
Figura 13 l'interfaccia di ricerca con griglia generata dal Web API e mantenuto da SignalR

Conclusioni

Ho dimostrato come costruire un progetto MVC ASP.NET e aggiungere un layout Web Form, controlli di terze parti AJAX e Web Form di routing ad esso. Ho generato l'interfaccia utente con fregi di MVC e attivato il contenuto Web API e SignalR. Questo progetto utilizzato caratteristiche da tutti e quattro i ASP.NET Framework per presentare un'interfaccia coerente, sfruttando le migliori caratteristiche di ogni componente. Si può fare lo stesso. Don' t scegliere un solo ASP.NET framework per il vostro prossimo progetto. Invece, sceglie di usarli tutti.

Jeff  Fritz  è un developer evangelist Telerik con più di 15 anni di esperienza costruire applicazioni Web multi-tenant su larga scala nel Software come un modello di servizio. Egli è un altoparlante INETA e mantiene un blog a csharpfritz.com. Lo si può trovare su Twitter a twitter.com/csharpfritz e potete contattarlo al jeff.fritz@telerik.com.

Grazie ai seguenti esperti tecnici per la revisione di questo articolo: Scott Hanselman (Microsoft) e Scott Hunter (Microsoft)