Integracja danych pomiędzy aplikacją ASP MVC a platformą Blogger bądź Wordpress

0

Witajcie jak w temacie.

Czy bawił się ktoś z Was w taka integrację?

Mam na myśli integrację aplikacji ASP MVC która współpracuje z bazą danych (zawierającą np. produkty) I te produkty chciałbym przesłać w postaci JSONa I odebrać go poprzez javascripta na platformie Blogger.

Do tego pewnie będę musiał stworzyć jakiś web api controller ktory wezmie te dane z bazy (wystarczy mi pewnie nazwa, ilosc, cena) a nastepnie akcja zwroci JSONResult ale jak potem odebrac tego JSONA?

1

Czyli jednym słowem chcesz zwrócić z jakiejś akcji rezultat w postaci json, żeby potem móc sobie to ajaxem pobrać?

To tu nie trzeba żadnego ApiController. Możesz użyć zwykłego kontrolera, i jego metody pomocniczej Json() zwracając JsonResult, na przykład mając model:

namespace WebFun1.Models
{
  public class Product
  {
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public int Amount { get; set; }
  }
}

i akcje:

using System.Collections.Generic;
using System.Web.Mvc;
using WebFun1.Models;

namespace WebFun1.Controllers
{
  public class ProductsController : Controller
  {
    public JsonResult Index()
    {
      var listOfProducts = new List<Product>
      {
        new Product { Id = 1, Name = "Banan", Amount = 31, Price = 2 },
        new Product { Id = 2, Name = "Frytki", Amount = 20, Price = 5 },
        new Product { Id = 3, Name = "Paczek", Amount = 10, Price = 2 },
        new Product { Id = 4, Name = "Pizza", Amount = 3, Price = 40 }
      };

      return Json(listOfProducts, JsonRequestBehavior.AllowGet);
    }
  }

Po wykonaniu tej akcji dostajemy ładny wynik:

[  
   {  
      "Id":1,
      "Name":"Banan",
      "Price":2,
      "Amount":31
   },
   {  
      "Id":2,
      "Name":"Frytki",
      "Price":5,
      "Amount":20
   },
   {  
      "Id":3,
      "Name":"Paczek",
      "Price":2,
      "Amount":10
   },
   {  
      "Id":4,
      "Name":"Pizza",
      "Price":40,
      "Amount":3
   }
]
1

Nie pisalem nigdy nic w wordpressie, ale google twierdzi, ze sie chyba da -> http://wordpress.stackexchange.com/questions/28229/consuming-an-external-api-in-wordpress

Co do wystawiania api, to najlepiej nie angazowac do tego ASP, nie ma sensu. Dobrym rozwiazaniem bedzie tutaj zwykly serwis RESTowy na Web Api, ktory potem konsumujesz sobie czymkolwiek, na przyklad aplikacja na wordpressie:)

0

Dzięki noname za bardzo konkretną odpowiedź.

Robie właśnie podobnie ale na WebAPI controlerze tak zeby bylo fajnie.

 
public class IntegrationController : ApiController
    {
        public TestContext _context { get; set; }

        public JsonResult IntegrateProductsWithPlatform()
        {
            using (_context = new TestContext())
            {
                var getProducts = _context.Products.ToList(); // tutaj wyciagam produkty z tabeli Product

                return Json(getProducts, JsonRequestBehavior.AllowGet);
            }

            
        }

        private JsonResult Json(List<Models.Product> getProducts, JsonRequestBehavior jsonRequestBehavior)
        {
            return Json(getProducts, JsonRequestBehavior.AllowGet);
        }

     
    }

Ale jak teraz tego JSONa gdzies odebrać I go zdeserializować?

Serwis RESTowy mowisz?

Tam tez bedzie metoda zwracająca jakiegoś JSONa I np. pobierająca go poprzez jakiś Plugin na Wordpressie?

1

No zwyczajnie ajaxem. :P Tylko jak chcesz robić cross-site requesty to afair musisz dodać coś takiego (albo odpowiednik, nie pamiętam czy w WebApi to się robi jakoś inaczej):

HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");

na początku akcji. (Najlepiej to upchnąć w jakiś filtr czy coś takiego)

A po stronie klienta masz zwykły javascript wysyłający żądanie i odbierający odpowiedź, np.

  <table id="products">
    <tr>
      <td>Name</td>
      <td>Amount</td>
      <td>Price</td>
    </tr>
  </table>

  <script type="text/javascript">
    $(document).ready(function () {
      $.get("http://localhost:50415/products", function (data) {
        data.forEach(function (product) {
          var row = $("<tr>")
            .append($("<td>").html(product.Name))
            .append($("<td>").html(product.Amount))
            .append($("<td>").html(product.Price));
          $("#products").append(row);
        });
      });
    })
  </script>
1

Glownym celem stawiania resta jest obsluga operacji crud (create/read/update/delete), czyli po prostu takie podstawowe operacje na danych. Taki rest zwraca wlasnie/przyjmuje wlasnie dane, czy one sa w formacie jsona, czy xmla, czy jakimkolwiek innym to sobie juz konfigurujesz - jedna linijka w configu. I to w zasadzie tyle, rest jest kompletnie niezalezny od klienta konsumujacego ten serwis, on tylko wystawia dane.
Do takiego resta mozesz sie podlaczac zarowno klientem dekstopowym (np wpf/silverlight/windows forms), jakims webowym (asp, czy cokolwiek innego), mozesz nawet przez przegladarke wejsc na adres webapi i dostaniesz normalnie dane - cala sztuczka polega na tym, zeby w kliencie, ktorym sie laczysz stworzyc sobie taki request, puscic go na adres webapi i po prostu odebrac dane;)

0

kurcze przyznam się, że nie chce mi to jakoś działać.

Mam taki controller:

 
public class IntegrationController : ApiController
    {
        public TestContext _context { get; set; }


        public JsonResult IntegrateProductsWithPlatform()
        {
            using (_context = new TestContext())
            {
                var getProducts = GetAllProducts()

                return Json(getProducts.AsEnumerable().ToList(), JsonRequestBehavior.AllowGet);
            }
        }

        public IEnumerable<Product> GetAllProducts()
        {
            var products = _context.Products.ToList();
            return products;
        }

        private JsonResult Json(List<Models.Product> getProducts, JsonRequestBehavior jsonRequestBehavior)
        {
            return Json(getProducts, JsonRequestBehavior.AllowGet);
        }
    }

I jak go uruchamiam to nie potrafi odnaleźć zasobu. jak dorwać się do tego linka o którym mówisz? Sorki nigdy tego nie robiłem.

0

Jak nie mieszales nic w route configu, to domyslny url wyglada tak: http://localhost:8080/api/Integration
A to, ze nie potrafi znalezc zasobu to jest ok, bo po odpaleniu aplikacji, strona startowa jest localhost:8080, a skoro nie definiowales zadnych defaultowych widokow to pod tym adresem nie ma co wyswietlac i wywala blad o brakujacym zasobie.

1

Dodałeś ten ApiController do projektu MVC? Na sucho?

Bo żeby to działało, to trzeba trochę rzeczy zrobić.
Stworzyć plik WebApiConfig.cs w App_Start

Domyślnie generowany jest taki, jak użyłeś odpowiedniego narzędzia do tworzenia kontrolera:

namespace WebFun1
{
  public static class WebApiConfig
  {
    public static void Register(HttpConfiguration config)
    {
      config.MapHttpAttributeRoutes();

      config.Routes.MapHttpRoute(
          name: "DefaultApi",
          routeTemplate: "api/{controller}/{id}",
          defaults: new { id = RouteParameter.Optional }
      );
    }
  }
}

Potem trzeba dodać odpalanie tej konfiguracji w Application_Start():

GlobalConfiguration.Configure(WebApiConfig.Register);

Na samej górze!!! (inaczej nie będzie działać, niezupełnie na samej górze koniecznie, ale to już mniej istotne :P).

Do tego metody muszą mieć czasowniki http w nazwie, np. GetProducts(), ważna część Get.

0

Dorobiłem również taki widget na platformie Blogger ale chyba nie jest on w stanie pobrać tego JSONa z localhosta :(

<span>Produkty w sklepie</span>

  <table id="products">
    <tr>
      <td>| Nazwa produktu | </td>
      <td> Ilość sztuk | </td>
      <td> Kwota do zapłaty | </td>
    </tr>
  </table>
 
  <script type="text/javascript">
    $(document).ready(function () {
      $.get("http://localhost:61746/integration", function (data) {
        data.forEach(function (product) {
          var row = $("<tr>")
            .append($("<td>").html(product.Name))
            .append($("<td>").html(product.Amount))
            .append($("<td>").html(product.Price));
          $("#products").append(row);
        });
      });
    })
  </script>
 

Tak wyglada klasa konfiguracyjna dla Web API

 
public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            // zezwolenie na przekazanie rowniez XMLa bo JSON zwraca sie domyslnie
            var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
            config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
        }
    }
0
n0name_l napisał(a):

Do tego metody muszą mieć czasowniki http w nazwie, np. GetProducts(), ważna część Get.

Opcjonalnie mozna tez stosowac dowolne nazwy, ale wtedy trzeba pamietac o atrybutach, HttpPost, HttpPut itd.

@Odyn, a probujac dostac sie przez przegladarke normalnie wyswietla Ci dane?

0

Okej musiałem zarejestrować to WebAPI w global.asax bo nie mialem

 
public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            GlobalConfiguration.Configure(WebApiConfig.Register); // zarejestrowanie naszego web api

            // dodanie mozliwosci formatowania XMLa
            GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("json", "true", "application/json"));


        }
0

Proponuje zrobic tak:

  • opdalasz visuala, new project, asp.net
  • z tych wewnetrznych templatow wybierz WebApi
  • odpal aplikacje i idz na adres localhost:8080/api/values
  • daj znac co wyswietlila przegladarka:)
0

Tylko zastanawiam się czy w tym javascripcie mam korzystać z metody $.get skoro ja mam web api controller ktory zwraca mi jsona I nie moge nad ta akcja wstawic atrybbutu [HttypGet] ani zadnego innego.

0

Zrobiłem od nowa to WebAPI. Nie rozumiem jak to działa.

Mam tabele z produktami, którą chce wysłać sobie z localhosta do innej strony na serwerze zewnętrznym.

W web api controlerze zrobilem sobie akcje:

 
 public JsonResult GetAllProducts()
        {
            var products = context.Products.ToList(); // wyciagam produktu
            return Json(products, JsonRequestBehavior.AllowGet); // tutaj blad
        }

Blad jest taki:
Error 1 The best overloaded method match for 'System.Web.Http.ApiController.Json<System.Collections.Generic.List<integracja.Models.Product>>(System.Collections.Generic.List<integracja.Models.Product>, Newtonsoft.Json.JsonSerializerSettings)' has some invalid arguments S:\SelfDevelopment\WebAPI\integracja\integracja\Controllers\IntegrationController.cs 81 20 integracja

0

WebAPI to nie MVC! WebApi samo sobie poradzi ze zwróceniem czy to jsona czy xmla, nie musisz mu tego mówić!

Zamień tą metodę na:

public List<Product> GetAllProducts()
{
  var products = context.Products.ToList();
  return products;
}
0

Zrobiłem tak jak mówiłeś ale jak mam teraz sprawdzić czy ta metoda działa? Nie wiem czy nie będę musiał włączyć tego cross command site scripting czy jakos tak :P

Jets dobra uruchomiłem :)

http://localhost:56913/api/integration

I przegladarka zapisala mi JSONA

[{"Id":1,"Name":"Produkt1","Quantity":34,"Price":5.00},{"Id":2,"Name":"Produkt2","Quantity":67,"Price":7.00}]

Ale ja chce tego JSONa przesłac na calkiem inna strone tj. blogspot.com i tam ja odebrac i wyswietlić.

0

Api nic nigdzie nie przesyła. To działa tak, że taki serwis sobie stoi i czeka na requesty. Przychodzi pan A (klient wpf/wordpress/blogspot) i pyta sie serwisu o dane (robi request GET), serwis mu zwraca wynik reuesta czy to w jsonie czy xmlu (wszystko da sie skonfigurowac) i klient sobie te dane zabiera do siebie do domu i to o niego zalezy co z nimi zrobi, czy je jakos sparsuje i powrzuca w kontrolki, czy po prostu zapisze do pliku, czy zrobi cokolwiek innego. Przyklad podawal w tym watku @n0name_l (chyba jquery o ile pamietam)

0

Na stronie bloga dodałem sobie widget w którym staram sie to debrać:

<span>Produkty w sklepie</span>

  <table id="products">
    <tr>
      <td>| Id </td>
      <td>| Nazwa produktu | </td>
      <td> Ilość sztuk | </td>
      <td> Kwota do zapłaty | </td>
    </tr>
  </table>
 
  <script type="text/javascript">
    $(document).ready(function () {
      $.get("http://localhost:56913/api/integration", function (data) {
        data.forEach(function (product) {
          var row = $("<tr>")
            .append($("<td>").html(product.Id))
            .append($("<td>").html(product.Name))
            .append($("<td>").html(product.Quantity))
            .append($("<td>").html(product.Price));
          $("#products").append(row);
        });
      });
    })
  </script>
 

Ale nic nie wyswietla sie chyba dlatego ze on nie ma dostepu do localhosta? Moze sie myle?

0

A masz ten serwis w ogóle uruchomiony w tym momencie kiedy sie do niego dobierasz?

0

Nie dojdziemy nigdy do końca tego wątku chyba.

Pokaż jaki błąd wypisuje (F12 w większości przeglądarek i klikasz na zakładkę console/konsola).

0

I postaw breakpointa na linijce data.forEach(function (product) (w przegldarce - f12) i podgladnij co jest z zmiennej data

0

Więc w Web API nie ma błędu żadnego natomiast na stronie bloga są takie:

user image

Ale to nie są blędy zwiazane z tym JSON ( tak mi się wydaje )

1

Nie dodałeś jQuery.

0

Ok racja. Teraz widzę, że ten JSON idzie tam ale jest inny błąd:

XMLHttpRequest cannot load http://localhost:56913/api/integration. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://modnysklep2013.blogspot.de' is therefore not allowed access.

0

-.-'
Przeczytaj pierwsze 2 zdania. http://4programmers.net/Forum/1113847

0

Dodałem metodę Application_BeginRequest w pliku global.asax

 
 public void Application_BeginRequest()
        {
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
        }

Tak to wygląda:)

<image> http://images.tinypic.pl/i/00633/f5cfwd6r38hs.png </image> A jak zrobić żeby ten serwis zawsze był uruchomiony? Czy podczas uruchamiania aplikacji on tez bedzie dzialal?
1

Ale to brzydko zrobiłeś. :(

Masz tu opisane jak to się po ludzku robi: http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api#enable-cors

A jak zrobić żeby ten serwis zawsze był uruchomiony?

Wrzucić go na jakiś hosting, ewentualnie postawić na lokalnym IIS, odblokować porty (i zrobić przekierowania jak masz NATa jakiegoś), ogarnąć sobie stałe IP i trzymać komputer włączony 24/d.

0

Chodzi mi ogólnie bo mam bardzo rozbudowaną aplikację sklepu i ten web api controller będzie znajdować się na serwerze lokalnym bądź zdalnym razem z całą aplikacją sklepu.

Chodzi mi tylko to, czy jak uruchomię aplikację sklepu to ten web api też będzie działać w tle?

1

Kontroler webapi dziala praktycznie tak samo jak zwykly kontroler asp mvc, z ta roznica ze zwraca dane zamiast widoku (w duzym uproszeczniu). Wiec jesli masz webowa aplikacje i w niej kilka kontrolerow asp, kilka web api i to uruchomisz to normalnie bedzie to sobie dzialalo;p

1 użytkowników online, w tym zalogowanych: 0, gości: 1