SAP+ASP.NET MVC + SignalR

SAP ERP üzeride tutulan verilerin, SAP ekosistemi dışında 3rd parti bir yazılım uygulamasıyla entegre etmek istediğimizde birçok yöntem bulabiliriz. RFC ile SAP dışına açılan bir web service veya .net connector ile sunulan bir dll ile direk bağlantı gibi yöntemler mevcut.

Bu yazıda, SAP üzerinde bulunan bir tabloya anlık olarak eklenen verilerin, ASP.NET MVC ile geliştirilmiş bir web uygulamasında yer alan tabloya SignalR teknolojisi kullanarak anlık yansıtılması konusunda örnek sunacağım.

Yukarıda bahsettiğim gibi, elimizde 2 farklı geliştirme ortamı bulunuyor,

  1. SAP ERP
  2. ASP.NET MVC Web Uygulaması + SignalR

Bu iki farklı ortamı birbiri ile konuşturmak için RFC ile sunulan bir web service kullanabiliriz veya SAP .Net Connector kullanabiliriz.
Bu uygulamada RFC ile sunulan web service kullanacağız.

İlk olarak SAP tarafındaki veri altyapımızı hazırlayalım. Bunun için RFC ile sunacağımız bir tablo oluşturuyor ve bu tabloya bağlı olarak Structure ve Table Type yapılarını gerçekleştiriyoruz.

Tablomuzu ve bu tabloyu sunacağımız RFC için gerekli olan Tablo Tipi ile bu tablo tipinin türeyeceği Structure alt yapısını oluşturduktan sonra, RFC için gerekli olan Function Group ve Function Module tarafını oluşturabiliriz. Function Module oluşturduktan sonra dikkat edilmesi gereken en önemli kısım Attributes sekmesinde er alan Processing Type alanında Remote-Enable Module işaretli olmasıdır. Yazdığımız fonksiyonun web service olarak dışarıya çıkartılacağını bu seçenek belirlemektedir.

Export Sekmesinde parameter Name alanına fonksiyonun döneceği tablo adını, Associated Type alanına ZSR_TY_DEMO tablo tipini tanımladıktan sonra Pass Value alanını işaretliyoruz.

Bu örnek için source code sekmesine sadece tablodaki verilerin hepsini çekecek bir select query yazıyoruz. Kendi uygulamanız için farklı geliştirmeler yapabilirsiniz.

FUNCTION ZSR_FM_DEMO.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  EXPORTING
*"     VALUE(ET_SR_LIST) TYPE  ZSR_TY_DEMO
*"----------------------------------------------------------------------


SELECT * INTO CORRESPONDING FIELDS OF TABLE ET_SR_LIST FROM
  ZSR_T_DEMO.


ENDFUNCTION.

Function module geliştirmesini tamamladıktan sonra bu fonksiyonu rfc olarak yayınlamak için sap menü sekmesinden

utilities -> more utilities -> create web service -> from the function module

adımlarını takip ederek web service için gerekli uyarlamaları tamamlıyoruz.

Web service işlemini tanımladıktan sonra SOAMANAGER üzerinden web service uyarlamalarını gerçekleştirip bize sunulan service url adresine ulaşıyoruz.

SAP tarafındaki tüm geliştirme ve uyarlamalarımız artık tamamlandı. ASP.NET MVC tarafında web uygulamamızı geliştirmeye başlayabiliriz.

Visual Studio üzerinden yeni proje seçeneği ile ASP.NET Web Application (.NET Framework) seçtikten sonra MVC seçeneği ile ilerliyoruz. Proje oluşturulduktan sonra ilk olarak NuGet Package Manager üzerinden SignalR paketini yüklüyoruz.

SignalR paketimizi yükledikten sonra proje solution kısmına hubs ismi ile bir klasör atıp içerisine new -> add -> new item ile OWIN Startup class ekliyoruz. OWIN class’ı içerisine aşağıdaki kod bloğunu ekleyerek, projenin ilk startup aşamasında SignalR sınıflarının çalıştırılmasını tetikliyor olacağız.

using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(Sap_SignalR_RealTimeData.hubs.Startup))]

namespace Sap_SignalR_RealTimeData.hubs
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}

startup tanımlanasından sonra hubs klasörünün içerisine new -> add -> new item ile SignalR Hub Class ekliyoruz. Eklediğimiz bu sınıf SignalR içerisindeki hubs sınıfından türetilmiş bir sınıftır.

hub sınıfımız içerisinde verilerin anlık okunması için ilk olarak alacağımız veri için bir model sınıfı oluşturuyoruz daha sonrasında ise SAP tarafında oluşturduğumuz web servisi projeye tanımlıyoruz.

Products sınıfını ekledikten sonra modelimizi aşağıdaki şekilde tanımlıyoruz.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Sap_SignalR_RealTimeData.Models
{
    public class Products
    {
        public string Material_Number { get; set; }
        public string Production_Plant { get; set; }
        public string Production_Date { get; set; }
    }
}

Web service için References alanına Web Service Reference ekleyerek servis url adresimizi tanımlıyoruz.

RFC servisi tanımladıktan sonra hubs sınıfımız içerisinde belirleyeceğimiz Timer ile istediğimiz aralıklarda bu servise bağlanacak ve verileri çekeceğiz.

Hubs sınıfı içerisindeki timer ve bu timer’a bağlı servis bağlantısı aşağıdaki gibidir. Bağlantı süresi 1000 mls olarak belirledim her 1 saniyede servise bağlanarak verileri çekecektir. Client tarafında yazacağımız javascript kodlaması için bu hub sınıfına HubName alanında saphubdata ismini verdim. servisten dönen datayı hub class’ından alabilmek için her gelen datayıhub.clients.all.addData parametre alanından alabiliriz.

using System.Collections.Generic;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using Sap_SignalR_RealTimeData.Models;

namespace Sap_SignalR_RealTimeData.hubs
{
    [HubName("saphubdata")]
    public class SapHub : Hub
    {
        private static readonly System.Timers.Timer _timer = new System.Timers.Timer();

        static SapHub()
        {
            _timer.Interval = 1000;
            _timer.Elapsed += TimerElapsed;
            _timer.Start();
        }

        static void TimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            var hub = GlobalHost.ConnectionManager.GetHubContext<SapHub>();

            var productList = new List<Products>();
            Sap_Service_Reference.ZSR_WS_DEMO service = new Sap_Service_Reference.ZSR_WS_DEMO();
            Sap_Service_Reference.ZSR_FM_DEMO param = new Sap_Service_Reference.ZSR_FM_DEMO();

            var response = service.ZSR_FM_DEMO(param).ET_SR_LIST;


            foreach (var item in response)
            {
                productList.Add(new Products
                {
                    Material_Number = item.MATNR,
                    Production_Date = item.URETIM_TARIHI,
                    Production_Plant = item.WERKS
                });
            }

            hub.Clients.All.addData(productList);
        }
    }
}

Client tarafında proje çalıştırıldığı anda connection işlemi ile hub’a bağlanarak yukarıdaki server side işlemleri gerçekleştirilecektir. Şimdi Client tarafındaki kodlamaya geçebiliriz.

Client tarafında önemli noktalardan birisi kütüphanelerin eklenmesidir. Projeyi ilk oluştururken eklediğimiz SignalR paketi içerisinde bize sunulan kütüphanelerin script olarak tanımlanması gerekmektedir.

<div class="row">
    <div class="col-md-12 col-sm-12 col-xs-12">
        <table id="sapTable">
            <thead>
                <tr>
                    <th>
                        <input type="checkbox">
                    </th>
                    <th>Material Number </th>
                    <th>Production Date </th>
                    <th>Production Plant </th>
                </tr>
            </thead>

            <tbody></tbody>
        </table>
    </div>
</div>


<script src="~/Scripts/jquery-3.3.1.min.js"></script>
<script src="~/Scripts/jquery.signalR-2.4.1.min.js"></script>
<script src="~/signalr/hubs" type="text/javascript"></script>
<script type="text/javascript">
    $(function () {

        // Gelen her malzeme numarasını bir dizide toplamak için array tanımlaması
        var array = [];

        // Hub sınıfına bağlanarak timer'ın aktifleştirilmesi
        var connection = $.connection.saphubdata;

        // Sınıf içerisindeki fonksiyon servisinden dönen datayı alma işlemi.
        connection.client.addData = function (message) {

            // Servis tarafından sunulan liste içerisinde loop işlemi.
            for (var i = 0; i < message.length; i++) {

                // Eğer gelen liste içerisindeki malzeme numarası daha önce gelmişse listeye ekleme !
                // Gelen liste içerisindeki malzeme numarası tabloda yoksa tabloya ekle !
                if (jQuery.inArray(message[i].Material_Number, array) == -1) {

                    // Tabloya eklenecek satırın tanımlanması ve tabloya eklenmesi.
                    $('#sapTable tbody').append('<tr class="even pointer">' +
                        '<td class="a-center "> <input type="checkbox" class="flat" name="table_records"></td>' +
                        '<td>' + message[i].Material_Number + '</td>' +
                        '<td>' + message[i].Production_Date + '</td>' +
                        '<td>' + message[i].Production_Plant + '</td>' +
                        '</tr>');

                    // Eklenen malzemenin tekrar kontrolü için ilk belirlenen diziye eklenmesi...
                    array.push(message[i].Material_Number);
                }
            }
        }

        // Bağlantıyı gerçekleştir.
        $.connection.hub.start();

    });
</script>

Son olarak projemizi çalıştırdığımızda ekrana gelen dataları görebilir, SAP üzerindeki tablomuza veriyi eklediğimizde sayfaya anında geldiğini sayfanın refresh edilmeden verinin yansıdığını aşağıdaki videoda olduğu gibi görebilirsiniz…


Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Google fotoğrafı

Google hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap /  Değiştir )

Connecting to %s