Archive | C# RSS feed for this section

.NET WEB API: REST Endpoints with C#

2 Mar

I have posted here and here on using MVC 5 to edit a database with no code but as much as I like MVC 5, there are times that I just want a service and I will code up a front-end from scratch. This also allows anyone else in my organization to use the service as they wish as well. In this post, I will walk you through using the Web API to connect a database table as a REST Endpoint and allow you to view records, add a record, modify a record and delete a record.

The Steps

First, create a new ASP .NET Application

1

 

Choose WEB API

2

Right click on Models and ADD ADO.NET Entity.

3

Choose the first option.

4

Enter your database and connection properties. You can then pick the database you want to use.

5

Select the table or tables you would like to make available.

6

Build the project. If you do not build at this point, you will get errors in the next steps.

7

Right click on Controller and add a new scaffolding item.

8

Pick the Web API 2 controller using Entity Framework.

9

Select the Model (Name chosen when you brought in the table). Also pick the content class you used in the first steps. It is a drop down and if you pick the wrong one you will get an error. Just retry choosing a different one if you can’t remember what you named it.

10

Launch the application in Chrome and go to the URL for your controller. The default is http://localhost:xxxx/api/controllername. Notice I am getting XML returned. This is not what I want.

11

Under the application start folder, open the WebApiConfig.cs file. Add these two lines:

var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == “application/xml”);
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);

 

12

Now browse to the URL again. JSON!

13

You can also add the primary key at the end of the url to get back a single record.

14

I will use the DHC Chrome plugin to show you how to make calls to the other endpoint not using GET. This is a fast way to test without having to write our front-end. POST to the URL and add Mr. T.

{“id”:5,”name”:”Mr. T”}

15In our application, we can see Mr T was added.

16

Let’s use PUT and edit Mr. T using his other name: B.A. Baracus.

17

It has been edited in our application.

18

Now let’s DELETE Mr. T.

19

He has been removed.

20

No code and we can view, add, edit and delete records in our database. Write a front-end using AJAX calls to each of the endpoints and pass a string representation of the object and you can do the same thing.

A note on posting to the endpoint.

Create a JavaScript object like Mr.T.

var mrT={“id”:5,”name”:”Mr. T”};

Now, to send it, you need to make it a string.

http.send(JSON.stringify(mrT));

This will allow your application to work properly. I made the mistake of trying to use parameters in the URL and that was a no go.

 

Advertisements

Revit and RabbitMQ: Passing Data in to Revit from Outside Applications

25 Oct

UPDATED:

I threw together a quick website using CherryPY to pass data to Revit. The QR Code pictured below, when scanned, will pull up the website, triggering the data in it to be sent to Revit. Picture a QR Code with info on a HVAC Unit, you scan it and the data is passed to Revit for when it was installed or serviced.

Sending Data in a URL to Revit. Data can be parsed to up date parameters of object.

Sending Data in a URL to Revit. Data can be parsed to update parameters of object.

QR Code with embedded data to send to Revit.

QR Code with embedded data to send to Revit.

 

 

 

 

 

 

 

 

 

 

***************************************************************************

ORIGINAL:

 

Modifying Revit from outside the program has been my primary interest for some time.

Initially, I was fascinated by the Revit DBLink plugin and wrote a few proof of concepts that relied on the following architecture:

Revit <—–> Database<—–>Outside Program

I have recently posted proof of concepts about sending data in to Revit from outside – skipping the database export– but used GIS as my example, arguing that because GIS and Revit use the same API language it should be possible.

I now have a working example in Revit. The architecture no longer requires a Revit DB to be exported.

Revit <——- RabbitMQ<———-Outside Program. (can be bidirectional if want it to)

I wrote a Revit Add-In that connects to a Messaging Queue and retrieves any waiting messages. Getting the message in to Revit is the hard part. Once in, we can use it to modify properties – like in the GIS example that drew points from a message.

The screenshots show the Add-In, No Messages Waiting, and a Message Coming In.

This is my proof of concept and the goal is to modify this program to allow the scanning of a QR code to send a message in to Revit and modify/add properties to an object. That architects looks like this:

Revit<—— RabbitMQ<——-WebServer <——- QR Code scanned by mobile device

The Qr Code Opens a URL with Parameters(http://somewhere.com/revit?id=123&wallheight=12

The WebServer is a CherryPy Script that reads in the parameters and passes them as a message to RabbitMQ using Pika.

The Revit Add-In gets the message and modifies the properties of the wall with ID=123

Interfaces in C#

13 Jun

I write code, but mostly single file “scripts.” I am familiar with Object Oriented Programming but rarely implement it – my programs are fairly simple tasks. In an attempt to expand my horizons and build more complex programs, I have attempted to learn some of the concepts of OOP that have confused me.

An interface seems like a simple thing – something that sits between two things and allows one to access the other. The gas pedal of your car is the interface to the cars engine. In programming, I understand an interface to be a contract that defines what a class must do. It can do more, and implement a number of interfaces, but must contain all the methods of each interface. I guess this allows you to replace classes and know that anything you put in will still have certain behaviors (methods). For my purposes, it is a good way to make sure that I define all the functionality I am supposed to – a kind of debugging check on my classes. I can define what a class should do in an interface and my debugger will hold me to it.

Here is a simple interface in C# (I like the idea of naming it a thing and the class a specific type of thing. One example I saw on a Java page named the interface bicycle and the class that implemented it SchwinnBicycle.)

interface Thing
{
void doSomething();
void doSomethingElse();

}

My class implementing the interface:

class SpecificThing : Thing
{
static void Main(string[] args)
{
SpecificThing it = new SpecificThing();
it.doSomething();
it.doSomethingElse();

}
public void doSomething()
{
Console.WriteLine(“I implement the Interface”);
}
public void doSomethingElse()
{
Console.WriteLine(“I implement the Interface too”);
}

}

If I do not implement the interface, I get an error in my debugger and cannot build.

I say it implements the interface but fail to include the methods.

I say it implements the interface but fail to include the methods.

When I add the methods doSomething() and doSomethingElse()

Add the methods and everything runs smoothly.

Add the methods and everything runs smoothly.

An interface defines the behavior of your class. It does NOT define how you must implement that behavior. A function doSomething() can do anything you want it to, but you must include it.

Embed Files in to a C# Executable

10 Jun

I needed to run some regedits on several computers and grab the IP Addresses. I was given all the scripts to run and had 2 options: include all the regedits in my C# code or execute the BAT that runs them all. I chose option 2 because I did not write them and wanted to keep them separate from my code. Also, I could not have users downloading multiple files or unzipping anything. So I chose to embed the files in an EXE, extract them when it runs, execute the BAT, email the IP, and delete them when done. I found the pieces of this code on StackOverflow.

To embed a file, you need to add it to your project in Visual Studio then under properties choose “embedded resource”.

Here is the full code. After you can find the code stripped to the bare minimum:

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Mail;
using System.Diagnostics;
using System.Reflection;
using System.IO;

namespace TSUnet
{
public partial class Form1 : Form
{
Assembly _assembly;
Stream _move;
Stream _move1;
Stream _move2;
Stream _move3;
Stream _move4;
Stream _cmd;
string os;
string printos;
public Form1()
{
InitializeComponent();
if (System.IO.File.Exists(“Quest_Move.reg”))
{

try
{
System.IO.File.Delete(“Quest_Move.reg”);
}
catch (System.IO.IOException e)
{
Console.WriteLine(e.Message);
return;
}
}
if (System.IO.File.Exists(“Quest_Move_1.reg”))
{

try
{
System.IO.File.Delete(“Quest_Move_1.reg”);
}
catch (System.IO.IOException e)
{
Console.WriteLine(e.Message);
return;
}
}
if (System.IO.File.Exists(“Quest_Move_2.reg”))
{

try
{
System.IO.File.Delete(“Quest_Move_2.reg”);
}
catch (System.IO.IOException e)
{
Console.WriteLine(e.Message);
return;
}
}
if (System.IO.File.Exists(“Quest_Move_3.reg”))
{

try
{
System.IO.File.Delete(“Quest_Move_3.reg”);
}
catch (System.IO.IOException e)
{
Console.WriteLine(e.Message);
return;
}
}
if (System.IO.File.Exists(“Quest_Move_4.reg”))
{

try
{
System.IO.File.Delete(“Quest_Move_4.reg”);
}
catch (System.IO.IOException e)
{
Console.WriteLine(e.Message);
return;
}
}
if (System.IO.File.Exists(“QuestMove.cmd”))
{

try
{
System.IO.File.Delete(“QuestMove.cmd”);
}
catch (System.IO.IOException e)
{
Console.WriteLine(e.Message);
return;
}
}
}

private void button1_Click(object sender, EventArgs e)
{
string name = System.Net.Dns.GetHostName();
IPHostEntry ipEntry = System.Net.Dns.GetHostEntry(name);
IPAddress[] addr = ipEntry.AddressList;

try
{
_assembly = Assembly.GetExecutingAssembly();
_move = _assembly.GetManifestResourceStream(“TSUnet.Quest_Move.reg”);
_move1 = _assembly.GetManifestResourceStream(“TSUnet.Quest_Move_1.reg”);
_move2 = _assembly.GetManifestResourceStream(“TSUnet.Quest_Move_2.reg”);
_move3 = _assembly.GetManifestResourceStream(“TSUnet.Quest_Move_3.reg”);
_move4 = _assembly.GetManifestResourceStream(“TSUnet.Quest_Move_4.reg”);
_cmd = _assembly.GetManifestResourceStream(“TSUnet.QuestMove.cmd”);

using (Stream file = File.OpenWrite(“Quest_Move.reg”))
{
CopyStream(_move, file);
}
using (Stream file = File.OpenWrite(“Quest_Move_1.reg”))
{
CopyStream(_move1, file);
}
using (Stream file = File.OpenWrite(“Quest_Move_2.reg”))
{
CopyStream(_move2, file);
}
using (Stream file = File.OpenWrite(“Quest_Move_3.reg”))
{
CopyStream(_move3, file);
}
using (Stream file = File.OpenWrite(“Quest_Move_4.reg”))
{
CopyStream(_move4, file);
}
using (Stream file = File.OpenWrite(“QuestMove.cmd”))
{
CopyStream(_cmd, file);
}

os = Environment.OSVersion.ToString();
if (os.Contains(“5.”))
{
printos = addr[addr.Length – 1].ToString();
}
else
{
printos = addr[3].ToString();
}

 

SmtpClient smtpserver = new SmtpClient(“Something.Something.Com”);
MailMessage mail = new MailMessage();
mail.From = new MailAddress(textBox1.Text.ToString());
mail.To.Add(“Me@Something.Com”);
mail.Subject = “From: ” + textBox1.Text.ToString() + ” Machine: ” + Environment.MachineName.ToString();
mail.Body = textBox1.Text.ToString() + “\r\n” + printos + “\r\n” + Environment.MachineName;

smtpserver.Send(mail);
Process.Start(“QuestMove.cmd”);
}

 
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), “Error”);
}
MessageBox.Show(“Please save your data, Log Off your machine and Call….”, “Done”);
if (System.IO.File.Exists(“Quest_Move.reg”))
{

try
{
System.IO.File.Delete(“Quest_Move.reg”);
}
catch (System.IO.IOException er)
{
Console.WriteLine(er.Message);
return;
}
}
if (System.IO.File.Exists(“Quest_Move_1.reg”))
{

try
{
System.IO.File.Delete(“Quest_Move_1.reg”);
}
catch (System.IO.IOException er)
{
Console.WriteLine(er.Message);
return;
}
}
if (System.IO.File.Exists(“Quest_Move_2.reg”))
{

try
{
System.IO.File.Delete(“Quest_Move_2.reg”);
}
catch (System.IO.IOException er)
{
Console.WriteLine(er.Message);
return;
}
}
if (System.IO.File.Exists(“Quest_Move_3.reg”))
{

try
{
System.IO.File.Delete(“Quest_Move_3.reg”);
}
catch (System.IO.IOException er)
{
Console.WriteLine(er.Message);
return;
}
}
if (System.IO.File.Exists(“Quest_Move_4.reg”))
{

try
{
System.IO.File.Delete(“Quest_Move_4.reg”);
}
catch (System.IO.IOException er)
{
Console.WriteLine(er.Message);
return;
}
}
if (System.IO.File.Exists(“QuestMove.cmd”))
{

try
{
System.IO.File.Delete(“QuestMove.cmd”);
}
catch (System.IO.IOException er)
{
Console.WriteLine(er.Message);
return;
}
}

}
public static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[8 * 1024];
int len;
while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, len);
}
}
}
}

 

And a very minimal version – a single embed without emailing or getting the IP:

namespace TSUnet

{
public partial class Form1 : Form
{
Assembly _assembly;
Stream _move;

public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
try
{
_assembly = Assembly.GetExecutingAssembly();
_move = _assembly.GetManifestResourceStream(“TSUnet.Quest_Move.reg”);

using (Stream file = File.OpenWrite(“Quest_Move.reg”))
{
CopyStream(_move, file);
}

}

catch (Exception ex)
{
MessageBox.Show(ex.ToString(), “Error”);
}}

public static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[8 * 1024];
int len;
while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, len);
}
}
}
}

 

Python in C# Using IronPython

16 May
C# calling Python

C# calling Python

I am better at Python than C# and when I couldn’t do something in C#, I would use:

System.Diagnostics.Process.Start(“DoItInPython.py”);

I had seen some posts about IronPython but always ignored them – to my own detriment. IronPython is the solution! You can call Python from C# or C# from Python. That means I can use System.Windows.Forms in my Python code.

Reading a post from MSDN, I put together this example that onClick() of button1 it passes the string from the textbox to a python function that just adds “Hello: ” to it. The python function is in name.py:

def printName(name):
return “Hello: “+name

The C# using IronPython:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Scripting.Hosting;
using IronPython.Hosting;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
var ipy = Python.CreateRuntime();
dynamic test = ipy.UseFile(@”C:\Documents and Settings\user\Desktop\name.py”);
MessageBox.Show(test.printName(textBox1.Text.ToString()));
}
}
}

You can go the other way too. Read the documentation for IronPython.net for more information than I will give here. Here is a Python script using a Windows Form.

Python calling System.Windows.Forms.MessageBox.Show()

Python calling System.Windows.Forms.MessageBox.Show()

You can see it took me a minute to get it working using my own DLL. Here is how to use a System DLL:

import clr

clr.AddReference(“System.Windows.Forms”)

import System.Windows.Forms as f

f.MessageBox.Show(“Hello From Python!”)

This will popup a MessageBox. Simple, right? I have a DLL on my desktop I wrote. As you can see in my screenshot above, I got it to come in almost the same way – just use AddReferenceToFileAndPath(“C:\desktop\yourname.dll”). Here is the full code to call the method MyName() – yourname is the namespace, Name is the class and myName is a method:

import clr

clr.AddReferenceToFileAndPath(“C:\desktop\yourname.dll”)

import yourname as n

a=n.Name()

a.myName(“Paul”)

Ouputs: ‘Hello:  Paul’

Now I can use Python in C# and Windows DLLs in Python. I’m positive this will come in handy.

Send MMS from ArcGIS Desktop Explorer – or Revit.

2 May
MMS from a button in Desktop Explorer.

MMS from a button in Desktop Explorer.

I had an earlier post on sending an MMS from C#. I have taken it one step further and dropped this code in to ArcGIS Desktop Explorer as a button. click the button and it takes a screenshot, pops up a form and attaches the screenshot. Can send as email or as an MMS. This should work for Revit too since the SDK is C# and all the code is from Microsoft not the GIS API.

 

When launching a form from the buttons in GIS, threading becomes an issue. Note the use of ShowDialog().  Also, in order to caputure the screen without the form in the way, grab it before launching the form. This is how you launch a form from the button in GIS:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Net.Mail;
using System.Windows.Forms;
using System.Drawing.Imaging;

using ESRI.ArcGISExplorer;
using ESRI.ArcGISExplorer.Application;
using ESRI.ArcGISExplorer.Mapping;
using ESRI.ArcGISExplorer.Geometry;
using ESRI.ArcGISExplorer.Data;
using ESRI.ArcGISExplorer.Threading;

namespace geomms
{
public class Button : ESRI.ArcGISExplorer.Application.Button
{

public override void OnClick()
{
int screenWidth = Screen.GetBounds(new System.Drawing.Point(0, 0)).Width;
int screenHeight = Screen.GetBounds(new System.Drawing.Point(0, 0)).Height;
Bitmap bmpScreenShot = new Bitmap(screenWidth, screenHeight);
Graphics gfx = Graphics.FromImage((Image)bmpScreenShot);
gfx.CopyFromScreen(0, 0, 0, 0, new Size(screenWidth, screenHeight));
bmpScreenShot.Save(“test.jpg”, ImageFormat.Jpeg);

Form1 a = new Form1();
a.ShowDialog();

}
}
}

 

 

Here is the code to send the MMS:

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Mail;
using System.Drawing.Imaging;

namespace geomms
{
public partial class Form1 : Form
{

public Form1()
{
InitializeComponent();

}

private void button1_Click(object sender, EventArgs e)
{
try
{
String strFileName = string.Empty;
MailMessage mail = new MailMessage();
SmtpClient SmtpServer = new SmtpClient(“embudo.cabq.gov”);
mail.From = new MailAddress(“pcrickard@cabq.gov”);
mail.To.Add(tobox.Text.ToString());
mail.Subject = subjbox.Text.ToString();
mail.Body = msgbox.Text.ToString();
strFileName = “test.jpg”;
System.Net.Mail.Attachment attachment;
attachment = new System.Net.Mail.Attachment(strFileName);
mail.Attachments.Add(attachment);

SmtpServer.Send(mail);
MessageBox.Show(“Sent Message”, “MMS by Paul”);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}

 

C# DataGridView Export

2 May
My .ini Magaer using DataGridView

My .ini Magaer using DataGridView

I need to manage a .ini file that contains data in the format id=value. There is some information in the first 6 lines that I deal with in my code, but for the most part the data can be dealt with by splitting on ‘=’.

This app loads the .ini in to a DataGridView and allows the user to search, edit, add or remove records. Lastly, any changes can be exported out to a new .ini file.

Here is the code to create a DataGridView, search columns, clear highlighted rows and save as text. Each function is easy to find as it is attached to a buttons onclick.

Here is the code for the form:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace ini
{
public partial class Form1 : Form
{

public Form1()
{
InitializeComponent();

 

dataGrid.AutoGenerateColumns = false;

DataGridViewTextBoxColumn titleColumn = new DataGridViewTextBoxColumn();
titleColumn.DataPropertyName = “SN”;
titleColumn.HeaderText = “Machine Name”;

DataGridViewTextBoxColumn postColumn = new DataGridViewTextBoxColumn();
postColumn.DataPropertyName = “Terminal”;
postColumn.HeaderText = “Terminal ID”;
dataGrid.Columns.Add(titleColumn);
dataGrid.Columns.Add(postColumn);

dataGrid.AllowUserToOrderColumns = true;
dataGrid.AllowUserToDeleteRows = true;
dataGrid.GridColor = Color.DarkSlateGray;

var reader = new StreamReader(File.OpenRead(“Terminal.ini”));
List<string> listA = new List<string>();
List<string> listB = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(‘=’);

if (line.Contains(“=”))
{
if (values[0] == null)
{
values[0] = “EMPTY”;
dataGrid.Rows.Add(values[0], values[1]);
}
else
{
dataGrid.Rows.Add(values[0], values[1]);
}
}
else
{

}

//Maybe use this later to search?
//listA.Add(values[0]);
//listB.Add(values[1]);

}
}

private void button1_Click(object sender, EventArgs e)
{
string searchValue = textBox1.Text;

dataGrid.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
try
{
foreach (DataGridViewRow row in dataGrid.Rows)
{
if (row.Cells[0].Value.ToString().Contains(searchValue))
{
row.Selected = true;

}

}

}
catch (Exception exc)
{

}
}

private void button4_Click(object sender, EventArgs e)
{
string searchValue = textBox1.Text;

dataGrid.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
try
{
foreach (DataGridViewRow row in dataGrid.Rows)
{
if (row.Cells[1].Value.ToString().Contains(searchValue))
{
row.Selected = true;

}

}

}
catch (Exception exc)
{

}
}

private void button2_Click(object sender, EventArgs e)
{
foreach (DataGridViewRow row in dataGrid.Rows)
{
row.Selected = false;
}
}

private void button3_Click(object sender, EventArgs e)
{
if (System.IO.File.Exists(“Terminal-fromApp.ini”))
{

try
{
System.IO.File.Delete(“Terminal-fromApp.ini”);
}
catch (System.IO.IOException excep)
{
Console.WriteLine(excep.Message);
return;
}
}

StringBuilder myString = new StringBuilder();
StreamWriter sw = new StreamWriter(“Terminal-fromApp.ini”, true);
// var headers = dataGrid.Columns.Cast<DataGridViewColumn>();
myString.Append(“[Settings]\r\n”+”START=GUI1\r\n”+”MAX=G999\r\n”+”[Mappings]\r\n” );
myString.AppendLine();

foreach (DataGridViewRow row in dataGrid.Rows)
{
var cells = row.Cells.Cast<DataGridViewCell>();
myString.Append(string.Join(“=”, cells.Select(cell => cell.Value )));
myString.AppendLine();

}
string q = myString.ToString();
string xx = q.Substring(0,q.LastIndexOf(‘=’));
sw.WriteLine(xx);
sw.Close();
MessageBox.Show(“File Exported”, “Done”);
}
}
}