go to post David Hockenbroch · Oct 30 Here's my small but useful contribution: Add an "Add Server to VS Code" Option to System Tray Icon
go to post David Hockenbroch · Oct 30 Look in the System Management Portal under System Administration, Security, Applications, Web Applications, and look for the /csp/sys application. That's the System Management Portal. You can probably set a required resource there, and then only people who have that resource should be able to access it. You'll probably want to make a new resource, not just use an existing one. Just make sure you have that resource before you make that change so you don't lock yourself out!
go to post David Hockenbroch · Oct 27 Calling the methods this way is effective for testing the methods, yes. You just want to get really familiar with the %CSP.Request class. This approach isn't a good way to troubleshoot issues with your routes, or with authentication, though, as it bypasses those steps. For that, you'd probably have to define %request appropriately, then call some of the methods your API inherits from %CSP.REST, but I'm not as familiar with those.
go to post David Hockenbroch · Oct 22 And in addition to all of that, one of the workarounds people seem to like using is to have things comma-separated and enclosed in " to make sure it's getting the right commas, but I'm working on ERP software for the millwork industry in America. We're still allergic to metric here, and we use " to mean inches and ' to mean feet, so we can't use those either!
go to post David Hockenbroch · Oct 22 I know it's odd, but I've had three separate companies ask me for data formatted this way in the past couple of years. I'm not sure why, other than that the pipe is less common to run into within the data than commas.
go to post David Hockenbroch · Oct 21 We have had a few people ask for a CSV using a pipe as a separator. If you run into that and need to open it in Excel, you do that by going to the data tab, then click From Text/CSV. It may detect the separator character automatically, but if not there is a place where you can set it. (You may want to right click on the GIF and open in new tab if it's too fuzzy.)
go to post David Hockenbroch · Oct 21 @Stephen Canzano , when you are testing you can also manually define %request and give it a body and whatever else it needs before you call your class method. For instance: set %request = ##class(%CSP.Request).%New() set %request.ContentType = "application/json" set %request.Method = "POST" set %request.Content = ##class(%CSP.CharacterStream).%New() set json = {}.%New() set json.firstname = "David" set json.lastname = "Hockenbroch" do %request.Content.Write(json.%ToJSON()) Then you can call your class methods and the %request object you usually manipulate in those methods will be defined.
go to post David Hockenbroch · Oct 21 @Evgeny Shvarov it's like this: try{ //Do things here } catch ex{ do ex.Log() return ex.AsStatus() } If you do this, then the error gets logged in the application error logs in the system management portal, and a JSON representation of the exception gets returned through the API.
go to post David Hockenbroch · Oct 15 I'm not 100% certain, but I think you could use: set osuser = ##class(%SYS.ProcessQuery).%OpenId($J).OSUserName set userprofile = "C:\Users\"_osuser
go to post David Hockenbroch · Oct 6 You can create and log exceptions so that they show up in the application error logs in the SMP. That's how I prefer to do things.
go to post David Hockenbroch · Sep 23 @Theo Stolker I'm not sure what you mean by, "I never liked the different behavior of embedded sql, like when you have no result, you have no easy way to find that out." When you run an embedded query, it sets a variable called SQLCODE. If SQLCODE = 0, query completed with results. If SQLCODE = 100, query completed with no results. If SQLCODE < 0, there was an error with the query.
go to post David Hockenbroch · Sep 15 FYI, in your "Building SQL In Strings" section, you can also still use %SQL.Statement like this: set stmt = ##class(%SQL.Statement).%New() // Note the question mark in the query. set query = "SELECT Name, Age FROM Patient WHERE ID=?" set sc = stmt.%Prepare(query) // You can add error handing here if the above status results in an error // Providing variables to the %Execute method will insert them where the question marks are in the query, in order set rs = stmt.%Execute(id)
go to post David Hockenbroch · Sep 11 Really you'd want to set a variable equal to the $TLEVEL at the start of your try, then in the catch calculate the difference between the starting $TLEVEL and the current $TLEVEL, then do that many TROLLBACK 1s.
go to post David Hockenbroch · Sep 10 Combining what you said about error handling and transactions and also returning a status, a very basic outline for a lot of methods could be something like: try{ TSTART //Do stuff here TCOMMIT return $$$OK } catch ex{ if $TLEVEL > 0{ TROLLBACK } return ex.AsStatus() } Some of us who write articles could do a better job of making this easier for you too, though. We like to use short forms of certain things, like {} and [] which are ##class(%Library.DynamicObject) and ##class(%Library.DynamicArray). I try to remember to use the latter in my articles just because it makes it easier to find the thing I'm talking about in the documentation. There are cases like that which are technically correct, but make it harder for beginners to learn.
go to post David Hockenbroch · Sep 2 I'm not sure why you're getting that error, but the Collection keyword is deprecated. You are already declaring the property as a list, so it should be unnecessary anyway.
go to post David Hockenbroch · Aug 22 Your NewsGetItem method has two parameters, version and id, but the route you have defined for it only has one parameter, id. The parameter lists need to match up and be in the same order. Try taking the version parameter our of the NewsGetItem class method.
go to post David Hockenbroch · Aug 20 In this case, you'd probably have to create a class method in ObjectScript that changes the namespace, then call it using classMethodVoid() from the IRIS native SDK. But you'd have to make sure the necessary class method exists in all of the namespaces you want to change to and from, including %SYS.
go to post David Hockenbroch · Aug 20 I just now took a closer look at this because of a comment made on one of my ideas on the idea portal, and that's great news for us! Our software is an ERP system, and we have some customers who have multiple locations that they sell things out of. We generally have them share one code database, but different global databases. The old way, where it stored the table tuning statistics with the code, made it unusable for us because each of those locations would have different orders, invoices, customers, etc., so tuning the table would help one namespace and potentially harm the others!
go to post David Hockenbroch · Aug 20 In ObjectScript, you would do: new $NAMESPACE set $NAMESPACE = "USER" In embedded Python, you can execute those commands using iris.execute: import iris iris.execute('new $NAMESPACE') iris.execute('set $NAMESPACE = "USER"') I am not far enough into embedded Python to know if that's considered a best practice or if there's another way, but it does work. Here are my results in a Python shell terminal session: >>> print(iris.system.SYS.NameSpace()) USER >>> iris.execute('new $NAMESPACE') >>> iris.execute('set $NAMESPACE = "%SYS"') >>> print(iris.system.SYS.NameSpace()) %SYS
go to post David Hockenbroch · Aug 15 This seems to work for positive posix times, but I'm not sure why the 846,976 microsecond offset is required. Maybe someone who understands this subject better can answer that one. All math, though, no string manipulation. set newposix = ##class(%Library.PosixTime).LogicalToDisplay(posix-(posix#1000000)+846976)