Delphi: What's wrong with REST API based on mO

2019-09-22 06:16发布

I try to build REST Web Server based on mORMot framework (Delphi) and have issue with getting data from remote DB.

Server.dpr

const
  CONN_STR =
    'DRIVER=SQL Server Native Client 10.0;UID=user;PWD=pass;server=server;'
    + 'Trusted_Connection=No;MARS_Connection=yes';
var
  Model: TSQLModel;
  RESTServer: TSQLRestServerDB;
  Application: TwoStreamgateApplication;
  HTTPServer: TSQLHttpServer;
  ODBCConnProp: TSQLDBConnectionPropertiesThreadSafe;
begin
  SQLite3Log.Family.Level := LOG_VERBOSE;
  SQLite3Log.Family.PerThreadLog := ptIdentifiedInOnFile;
  ODBCConnProp := TODBCConnectionProperties.Create('', CONN_STR, 'wo', 'wo');
  try
    ODBCConnProp.ThreadingMode := tmMainConnection;
    Model := CreateModel;
    VirtualTableExternalRegisterAll(Model, ODBCConnProp);
    try
      RESTServer := TSQLRestServerDB.Create(Model, ':memory:');
      try
        RESTServer.DB.Synchronous := smNormal;
        RESTServer.DB.LockingMode := lmExclusive;
        RESTServer.CreateMissingTables;
        Application := TwoStreamgateApplication.Create;
        try
          Application.Start(RESTServer);
          HTTPServer := TSQLHttpServer.Create('8092', [RESTServer]
{$IFNDEF ONLYUSEHTTPSOCKET}, '+', useHttpApiRegisteringURI{$ENDIF});
          try
            HTTPServer.RootRedirectToURI('api/default');
            RESTServer.RootRedirectGet := 'api/default';
            writeln('"MVC WOStreamgate Server" launched on port 8092 using ',
              HTTPServer.HttpServer.ClassName);
            writeln(#10'You can check http://localhost:8092/api/info for information');
            writeln('or point to http://localhost:8092 to access the web app.');
            writeln(#10'Press [Enter] to close the server.'#10);
            readln;
            writeln('HTTP server shutdown...');
          finally
            HTTPServer.Free;
          end;
        finally
          Application.Free;
        end;
      finally
        RESTServer.Free;
      end;
    finally
      Model.Free;
    end;
  finally
    ODBCConnProp.Free;
  end;

Model is described below in ServerModel.pas unit

type
  TSQLBaseData = class(TSQLRecord)
  private
    FName: RawUTF8;
    FDetailURL: RawUTF8;
    FLogoURL: RawUTF8;
    FDescription: RawUTF8;
  published
    property Name: RawUTF8 read FName write FName;
    property Description: RawUTF8 read FDescription write FDescription;
    property LogoURL: RawUTF8 read FLogoURL write FLogoURL;
    property DetailURL: RawUTF8 read FDetailURL write FDetailURL;
  end;

  TSQLStation = class(TSQLBaseData)
  end;

function CreateModel: TSQLModel;

implementation

function CreateModel: TSQLModel;
begin
  result := TSQLModel.Create(
    [TSQLStation],
    'api');
end;

View model in ServerViewModel.pas unit

TServerApplication = class(TMVCApplication, IServerApplication)
  public
    procedure Start(aServer: TSQLRestServer); reintroduce;
    procedure StationView(ID: TID; out Station: TSQLStation);
  end;

implementation 

procedure TServerApplication.Start(aServer: TSQLRestServer);
begin
  inherited Start(aServer,TypeInfo(IServerApplication));
  fMainRunner := TMVCRunOnRestServer.Create(Self).
    SetCache('Default',cacheRootIfNoSession,15);
  aServer.Cache.SetCache(TSQLStation);
end;

procedure TServerApplication.StationView(ID: TID; out Station: TSQLStation);
begin
  RestModel.Retrieve(ID, Station);
end;

and now once I type http://localhost:8092/api/station/10 in browser, I get response

{ "errorCode":404, "errorText":"Not Found" }

in case I type http://localhost:8092/api/stationview/10 in browser I get rendered page, but without info about station=10 or any other.

Where did I make a mistake? I want simply get JSON-response to my request

UPDATE:

Another info that can help. Once I try the query

procedure TestQuery();
var
  SQLDBConnection: TODBCConnection;
  Q: TQuery;
begin
  SQLDBConnection := TODBCConnection.Create(ODBCConnProp);
  Q := TQuery.Create(SQLDBConnection);
  try
    Q.SQL.Clear; // optional
    Q.SQL.Add('select * from dbo.Station');
    Q.Open;
...

I catch an error:

Project Server.exe raised exception class EODBCException with message 'TODBCStatement - TODBCLib error: [HY106] [Microsoft][SQL Server Native Client 10.0]Fetch type out of range (0) '.

1条回答
兄弟一词,经得起流年.
2楼-- · 2019-09-22 06:52

Solution is very simple - need to add:

Database=myDataBase;

to

CONN_STR = 'DRIVER=SQL Server Native Client 10.0;UID=user;PWD=pass;server=server;' + 'Trusted_Connection=No;MARS_Connection=yes';Database=myDataBase;

Thanks Arnaud for great framework!!!

查看更多
登录 后发表回答