none
WebApi Soluzione Modulare RRS feed

  • Domanda

  • Ciao a tutti. Volevo alcuni chiarimenti per quanto riguardano le web api asp.net mvc.

    Io vorrei creare un infrastruttura che mi permette di poter accedere indipendetemente dall'interfaccia che sto utilizzando(aso.net mvc,javascript,hatml5,java,android,ios) ad dei servizi web(webapi).

    Quindi lato client posso utilizzare qualsiasi cosa, mentre lato server sto utilizzando le webapi entity framewrok code first e ms sql.

    Ho cresato una soluzione contenente tre progetti:

    1)Progetto.Data -> qui ho inserito tutte le entità per potermi creare il db , mi creo i repository e il context.

    2)Progetto.WebApi-> qui ho creato semplicemente un progetto vuoto dove ho inserito i ApiController.

    3)Progetto.UI-> questo per ora e un progetto in asp.net mvc però potrei cambiare con qualsiasi altro ti po di linguaggio lato client.

    Il mio problema e che dal progetto.UI non riesco ad accedere ai apicontroller che si trovano nel progetto.WebApi.

    Questo è lo script che ho inserito nella mia Index.cshtml che si trova in Progetto.UI:

    <script type="text/javascript">
        var admin = {
            Username: "admin",
            Password:"admin"
        };
        function Login()
        {
    
            var url = '/api/AdminApi/EffettuaLogin';
            $.ajax({
                url: url,
                data: JSON.stringify(admin),
                type: 'POST',
                contentType: "application/json",
                success: function(result) {
                    console.log(result);
                    }
                }
            });
        };
    </script>

    Qui il m io url dovrebbe indirizzarmi nei controller(ApiController) che si trovano in Progetto.WebApi. Come faccio? è giusto questo approccio per raggiungere il mio obbiettivo finale?

    Perche ovviamente se eseguo questo script mi dice che non trova la risorsa xke la cerca in Progetto.UI che è il progetto di avvio, anziche cercarla in Progetto.WebApi.

    mercoledì 9 luglio 2014 13:25

Risposte

  • L'approccio di separazione lo trovo corretto, così sei pronto al multi-tier, puoi installare le api su server diversi da quelli della UI.

    Il problema che hai è dovuto agli indirizzi, ovviamente separando hai bisogno di dargli un indirizzo completo, e con iis express, non hai grossi problemi, perchè quando runni l'applicazione, iis/vs si rende conto che la solution ha più di un web project, e li attiva tutti, in questo modo sono pronti e in ascolto entrambi nel tuo caso; quindi l'unica cosa che devi fare e dargli il path, vai nelle proprietà del progetto -> web, e imposta come url nel tuo js tutto il percorso per intero:

    var url = 'http://localhost:4690/api/AdminApi/EffettuaLogin';

    Chiaramente schiantarlo nel codice non è una buona cosa, e quindi ti puoi fare una classe di configurazione, dove tieni tutti gli url per ogni servizio che chiamerai.

    Non mi dispiace il modello che hanno fatto nel template asp.net "single page application", dove hai una classe js AppDataModel che si preoccupa di tutto l'accesso ai dati, e che quindi conosce anche gli indirizzi:

    function AppDataModel() {
        var self = this,
            // Routes
            changePasswordUrl = "/api/Account/changePassword",
            registerUrl = "/api/Account/Register";
    
        // Operations
        self.changePassword = function (data) {
            return $.ajax(changePasswordUrl, {
                type: "POST",
                data: data,
                headers: getSecurityHeaders()
            });
        };
    
        self.register = function (data) {
            return $.ajax(registerUrl, {
                type: "POST",
                data: data
            });
        };
    }
    



    Michael Denny [MVP - Visual C#]

    mercoledì 9 luglio 2014 14:13
  • Devi inserire in questo caso un percorso assoluto (come consigliato da Michael).
    Altra cosa, essendo su domini diversi ricordati che devi abilitare/implementare CORS nelle Web API, e qui trovi una guida che ti spiega il tutto:
    http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

    ciao


    Andrea Dottor
    Microsoft MVP - ASP.NET/IIS
    http://blog.dottor.net

    mercoledì 9 luglio 2014 15:17
    Moderatore

Tutte le risposte

  • L'approccio di separazione lo trovo corretto, così sei pronto al multi-tier, puoi installare le api su server diversi da quelli della UI.

    Il problema che hai è dovuto agli indirizzi, ovviamente separando hai bisogno di dargli un indirizzo completo, e con iis express, non hai grossi problemi, perchè quando runni l'applicazione, iis/vs si rende conto che la solution ha più di un web project, e li attiva tutti, in questo modo sono pronti e in ascolto entrambi nel tuo caso; quindi l'unica cosa che devi fare e dargli il path, vai nelle proprietà del progetto -> web, e imposta come url nel tuo js tutto il percorso per intero:

    var url = 'http://localhost:4690/api/AdminApi/EffettuaLogin';

    Chiaramente schiantarlo nel codice non è una buona cosa, e quindi ti puoi fare una classe di configurazione, dove tieni tutti gli url per ogni servizio che chiamerai.

    Non mi dispiace il modello che hanno fatto nel template asp.net "single page application", dove hai una classe js AppDataModel che si preoccupa di tutto l'accesso ai dati, e che quindi conosce anche gli indirizzi:

    function AppDataModel() {
        var self = this,
            // Routes
            changePasswordUrl = "/api/Account/changePassword",
            registerUrl = "/api/Account/Register";
    
        // Operations
        self.changePassword = function (data) {
            return $.ajax(changePasswordUrl, {
                type: "POST",
                data: data,
                headers: getSecurityHeaders()
            });
        };
    
        self.register = function (data) {
            return $.ajax(registerUrl, {
                type: "POST",
                data: data
            });
        };
    }
    



    Michael Denny [MVP - Visual C#]

    mercoledì 9 luglio 2014 14:13
  • Devi inserire in questo caso un percorso assoluto (come consigliato da Michael).
    Altra cosa, essendo su domini diversi ricordati che devi abilitare/implementare CORS nelle Web API, e qui trovi una guida che ti spiega il tutto:
    http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

    ciao


    Andrea Dottor
    Microsoft MVP - ASP.NET/IIS
    http://blog.dottor.net

    mercoledì 9 luglio 2014 15:17
    Moderatore
  • grazie per l'aiuto ho dato un occhiata e sono riuscito a far comunicare il mio orogetto web con le web api utilizzando cors.

    Pero adesso mi chiedo una cosa non mi e molto chiaro  una cosa.

    Facciamo un esmepio  ho un ApiController: AdminApiController, con un metodo EffettuaLogin.

    Se io ho il progetto web api su localhost:1840 e il mio progetto web su localhost:2840.

    quindi per accedere a quel metodo il mio url sara: http://localhost:1840/api/AdminApi/EffettuaLogin.

    Ma se dovessi ccedere a queste webapi anche da un applicazione desktop o mobile cosa dovrei fare? dovrò utilizzare il mio url: http://localhost:1840/api/AdminApi/EffettuaLogin. E cosa succede che ho messo come annotazione nel mio ApiController:    [EnableCors(origins: "http://localhost:2840", headers: "*", methods: "*")]???

    Utilizzando cors devo dire qual 'è il sito di orgine. quindi se io ho diversi siti dovrei crearmi un "Custom CORS Policy Providers" come spiegato nel link giusto?



    mercoledì 9 luglio 2014 19:59
  • CORS è valido solo per le chiamate da javascript. Se chiami i servizi da codice C# o altro, non vengono controllati gli header di cors.

    Altra cosa, sull'attributo EnableCors puoi comunque specificare più domini.

    ciao


    Andrea Dottor
    Microsoft MVP - ASP.NET/IIS
    http://blog.dottor.net

    giovedì 10 luglio 2014 09:20
    Moderatore
  • e puoi anche specificare the wildcard anche per origins.

    indirizzi multipli

    [EnableCors(origins: "http://www.contoso.com,http://www.example.com", 
        headers: "*", methods: "*")]

    e wildcard

    // Allow CORS for all origins. (Caution!)
    [EnableCors(origins: "*", headers: "*", methods: "*")]

    che trovi spiegato nell'articolo linkato alla sezione "Specify the Allowed Origins".


    Michael Denny [MVP - Visual C#]

    giovedì 10 luglio 2014 13:20
  • Molto interessante anche il fatto che puoi abilitarlo per tutti i controller creandoti un provider factory, che a sua volta si basa su un estensione di un interfaccia per crearti un tuo attributo Cors, in modo di dovere scrivere solo una volta tutta la policy, e potere leggere da configurazione la lista dei domini da aggiungere, ecc...

    Vedi sempre il solito post, alla sezione "Custom CORS Policy Providers".

    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
    public class MyCorsPolicyAttribute : Attribute, ICorsPolicyProvider 
    {
        private CorsPolicy _policy;
    
        public MyCorsPolicyAttribute()
        {
            // Create a CORS policy.
            _policy = new CorsPolicy
            {
                AllowAnyMethod = true,
                AllowAnyHeader = true
            };
    
            // Add allowed origins.
            _policy.Origins.Add("http://myclient.azurewebsites.net");
            _policy.Origins.Add("http://www.contoso.com");
        }
    
        public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request)
        {
            return Task.FromResult(_policy);
        }
    }

    [MyCorsPolicy]
    public class TestController : ApiController
    {
        .. // 
    public class CorsPolicyFactory : ICorsPolicyProviderFactory
    {
        ICorsPolicyProvider _provider = new MyCorsPolicyProvider();
    
        public ICorsPolicyProvider GetCorsPolicyProvider(HttpRequestMessage request)
        {
            return _provider;
        }
    } 

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.SetCorsPolicyProviderFactory(new CorsPolicyFactory());
            config.EnableCors();
    
            // ...
        }
    }




    Michael Denny [MVP - Visual C#]


    • Modificato Michael C. Denny giovedì 10 luglio 2014 13:24 riportato codice per comodità
    giovedì 10 luglio 2014 13:23
  • grazie ora approfondisco. 

    Questo mio portale avra un dominio ad esempio www.dominio.com

    ogni mio cliente potra avere un sottodomino www.cliente1.dominio.com, www.cliente2.dominio.com e cosi via, siccome posso eseere molti ade esempio un centinaio, non mi sembra il caso di dover abilitare ogni sottodominio per l'accesso cors delle webapi

    giovedì 10 luglio 2014 13:25
  • per abilitarlo a livello globale è più semplice in questo modo ;-)
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            var cors = new EnableCorsAttribute("www.example.com", "*", "*");
            config.EnableCors(cors);
            // ...
        }
    }

    ciao

    Andrea Dottor
    Microsoft MVP - ASP.NET/IIS
    http://blog.dottor.net

    giovedì 10 luglio 2014 13:27
    Moderatore
  • Se ricordo bene mi pare si possa inserire come regola "*.dominio.com"

    ciao


    Andrea Dottor
    Microsoft MVP - ASP.NET/IIS
    http://blog.dottor.net

    giovedì 10 luglio 2014 13:29
    Moderatore
  • grazie molto gentile :D

    Ma invece adesso sto probando ad intergarire con le web api da un controller di un progetto asp.net mvc pero non riesco a mettere il debug nel progetto dove ci sono le web api, come si procede per ispeizonare il codice?

    giovedì 10 luglio 2014 13:34
  • Se vai nelle proprietà della soluzione, nel tab 'Startup Project' puoi selezionare l'avvio multiplo. Così facendo, quando premi F5 ti partono in debug entrambi i progetti.

    Un avviso, quando hai domande che non sono inerenti al thread corrente (come potrebbe essere quest'ultima), sarebbe meglio aprire un nuovo thread, questo per facilitare la ricerca ad altri utenti che potrebbero avere la stessa problematica/dubbio. ;-)

    ciao


    Andrea Dottor
    Microsoft MVP - ASP.NET/IIS
    http://blog.dottor.net

    giovedì 10 luglio 2014 13:45
    Moderatore
  • hai ragione la prossima volta apro un nuovo thread.

    grazie per le risposte e per il supporto, adesso ho un bel po di cose da studiare XD

    giovedì 10 luglio 2014 14:23