Viser opslag med etiketten c#. Vis alle opslag
Viser opslag med etiketten c#. Vis alle opslag

torsdag den 8. december 2016

Using C# .NET for auto-responding to SurveyMonkey surveys


If you need to do auto-responding to SurveyMonkey surveys, you can perchance use the below C# code as a source of inspiration.

I used it for testing a survey that we had running internally. Please bear in mind that your company's SurveyMonkey-subscription might put a cap on the number of survey-responses.

Basically it works by utilizing the Selenium library (download it care of Nuget) for web-page testing. I used the Chrome web-driver because it didn't store cookies or history for the browser session. I also included a unique temporary value for when accessing the survey, or I would get the "you've already responded"-message.

    class Program
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 58; i++)
            {
                RespondToSurvey();
                Console.WriteLine(i);
            }
        }

        private static void RespondToSurvey()
        {
            OpenQA.Selenium.Chrome.ChromeDriver driver = new OpenQA.Selenium.Chrome.ChromeDriver();

            string baseUrl = $@"https://da.surveymonkey.com/r/?tempValue=" + DateTime.Now.Ticks;

            driver.Navigate().GoToUrl(baseUrl + "/");

            Actions actions = new Actions(driver);
            IWebElement radioBtn = driver.FindElementById("72374030_573987619");
            actions.MoveToElement(radioBtn).Click().Perform();

            var element = driver.FindElement(By.Name("surveyForm"));
            element.Submit();

            driver.Close();
        }
    }

onsdag den 9. oktober 2013

Mocking session state in a asp.net mvc4 unit test using Moq


I recently spent more time than I'd liked to figure out how to mock session state within an ASP.NET MVC test project. So here's the solution to that one, so hopefully you won't spend as much time as I.

Important disclaimer: I was all over the dial to search for info, but most of what I dug up was related to asp.net mvc 3. This below solution works for me with ASP.NET MVC 4 and Moq as mocking framework.

Consider the following controller and single action-method:


public class HomeController : Controller
{
public HomeController()
{
// default constructor, usually you'd inject some repository or what not here, but for this example we'll keep it simple
}

public ViewResult TestMe()
{
System.Diagnostics.Debug.WriteLine(Session["selectedMonth"]);
System.Diagnostics.Debug.WriteLine(Session["selectedYear"]);
return View();
}
}


The action-method references the current httpcontext's Sesson collection. So if we instantiate a 'HomeController' and try to obtain a ViewResult when calling the action-method, our unit test will fail with a NullReferenceException.

So, since the action-method wants to know about the Session collection, which resides in the HttpContext for the request to the method, we need to provide a HttpContext object. The below unit test code creates a mock HttpContext object, hooks it up to a mock Session object and passes it the instantation of the controller - and the test will then pass, as now the action-method has a HttpContext to reach into and yank out the Session info.


[TestMethod]
public void TestActionMethod()
{
// create the mock http context
var fakeHttpContext = new Mock();

// create a mock session object and hook it up to the mock http context
var sessionMock = new HttpSessionMock {{"selectedYear", 2013}, {"selectedMonth", 10}};
var mockSessionState = new Mock();
fakeHttpContext.Setup(ctx => ctx.Session).Returns(sessionMock);

// ... and here's how to attach a http context identity, just in case you'll come to need that, too
var fakeIdentity = new GenericIdentity("mno@ucsj.dk");
var principal = new GenericPrincipal(fakeIdentity, null);
fakeHttpContext.Setup(t => t.User).Returns(principal);

// we'll need to hook our http context up to a controller context mock - because we can't provide our controller with the http context mock directly
var homeControllerMock = new Mock();
homeControllerMock.Setup(foo => foo.HttpContext).Returns(fakeHttpContext.Object);

// all set up, now we'll instantiate the controller and pass our controller context object into its 'controllerContext' property
var target = new HomeController()
{
ControllerContext = homeControllerMock.Object
};

// ... and the below call to the action method won't throw a nullReferenceException, because now it has a Session state to dig into
ViewResult result = target.TestMe();

// ... and so the test will pass
Assert.AreEqual(string.empty, result.ViewName);
}

mandag den 23. september 2013

Contact web api from InfoPath Designer 2013

I was having some trouble getting values from my home-brewed web api into a InfoPath Designer 2013 form, so I wanted to document the solution for those of you out there perhaps struggling with this as well.

I was calling a simple 'Hello World'-web api that would return a string. My simple aip looks like this:


namespace ADlookup.Controllers
{
/* model */
public class employee
{
public string employeeId { get; set; }
public string bossId { get; set; }

}


public class ADLookupController : ApiController
{
[HttpGet]
public employee getNearestBossId([FromUri] string id)
{
return new employee()
{
employeeId = id,
bossId = id
};

}
}
}


However, upon calling this api in InfoPath Designer 2013, I got the following error message:



... to indicate the xml structure is invalid.

I didn't get it - when I called the service directly from my browser, valid xml was returned!:



The problem, as it turned out, was of course the one that as opposed to the xml displayed by my browsers, the InfoPath Designer application - correctly - retrieved the data by way of json, the web api's default MO.

So, in order to serve up only XML, for InfoPath to agree with, we'll strip away the web api's possibility of serving up json altogether. Modify your WebApiConfig to resemble the below, though of course take into consideration the routes you have for your own app:


public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);

// tbe below must be enabled if this rest service is used with infopath designer 2013 - it only accepts xml data.
// thus we'll remove the json return type
var formatters = GlobalConfiguration.Configuration.Formatters;
formatters.Remove(formatters.JsonFormatter);

}
}


Now, as we re-publish the web api service, we can try once more the url in InfoPath, which will now allow us to proceed to the next step:


Intriguingly, on a completely different note, the 'get data from http rest service' workflow component in Sharepoint Designer 2013 works off JSON, as opposed to XML! But that's a blog-entry for another rainy day.

Hope this helps someone, anyone,

thanks for reading.

onsdag den 3. juli 2013

Linq-to-sql enums support


I don't much like it when I must specify hard-coded values into my code. It can be a debugging nightmare, furthermore it looks ghastly. Microsoft's Sql Server OR-mapper linq-to-sql, which I like very much, unfortuantely do not have built-in designer support for generating enums from lookup-tables, which has previously found me doing that hard-coding I do not like to do. Well, no more - look on.

Consider the examples database-tables:


The 'periodStatusId' field is the one that I would ideally want to fill in as ...


myObject.periodStatusId = periodStatusIdEnum.OpenedStatus


... as opposed to ...


myObject.periodStatusId = databaseContext.PeriodStatus.Single( foo => foo.Description.Equals("Opened"));


Well there's a will and a way. What we can do is pre-define an enum and alter our database-context to reflect it. So, in your database-layer, define an enum and copy its values from the database. Like this:


public enum PeriodStatusEnum
{
ClosedByUser = 1,
ClosedBySystem = 2,
ReOpenedByUser = 3
}


Above, the integer corresponds to the auto-incrementing interger id of the lookup-table, the text corresponds to the description field.

It, well, it sucks, to have to pre-define the enumeration. Much preferred would be to do this in the designer, but that's not possible with linq-to-sql. So pre-define it we do, in the know that at least this will be a few hundred percent better than going hard-code style.

Now the enum has been created, we'll refer to this instead of the database's native type in the datacontext. Change both the lookup-table's and the referencing table's field types to your enum, pre-fixed with a 'global::' value, i.e. global::yourNamespace(s).periodStatusEnum. Like so:


That's it - now you can use your enumeration as opposed to actively looking up the value. Like this:


TidsRegPeriode period = new TidsRegPeriode();

// populate field by referencing your enumeration
period.periodeStatusId = timeRegistrering.Domain.PeriodStatusEnum.ReOpenedByUser;

... other fields populated...

dbContext.TidsRegPeriodes.InsertOnSubmit(period);
dbContext.SubmitChanges();


Again, it would be tremendously better if we could specify enums in the designer. But we can't - so this is a heck of a lot better.

fredag den 14. juni 2013

Razor calendar table

If you need to build a calendar-table in Razor, look no further, here's a snippet that'll accomplish just that:



@{
System.Globalization.GregorianCalendar cal = new System.Globalization.GregorianCalendar();

var firstDayInMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
int daysInMonth = cal.GetDaysInMonth(DateTime.Now.Year, DateTime.Now.Month);

DayOfWeek firstWeekday = cal.GetDayOfWeek(firstDayInMonth);
var dayNo = (int)firstWeekday;
int daysInMonthCounter = 1;
}

<table id="timeRegCalendarTable">
<thead>
<tr>
@for (int i = 0; i <= 6; i++)
{
<td>@CultureInfo.CurrentCulture.DateTimeFormat.DayNames[i]</td>
}
</tr>
</thead>
<tbody>
@while (daysInMonthCounter <= daysInMonth)
{
<tr>
@for (int j = 0; j <= 6; j++)
{
if (j == dayNo && daysInMonthCounter == 1)
{
<td>@daysInMonthCounter</td>
daysInMonthCounter++;
}
else
{
if (daysInMonthCounter > 1 && daysInMonthCounter <= daysInMonth)
{
<td>@daysInMonthCounter</td>
daysInMonthCounter++;
}
else
{
<td> </td>
}
}
}
</tr>
}
</tbody>
</table>


Hope it'll save you a half an hour.

onsdag den 8. maj 2013

Kinect Painting demo - simple setup


I went looking for a simple Kinect demo in which the user's right hand would be tracked and used as a paint-brush. I found some example projects here and there, but they were either rather elaborate with a bunch of functionality not required for a simple demo, or using third-party dll's.

So I put together my own simple thing, which I'm making available for download here.

I must confess to being not particularly impressed with the Kinect itself. The premise of the device is extraordinary, and it does function as the product description promises, but I found it slow in updating. It cannot in its present version be used as a "live" paint-application, as there will be a too noticable delay in its registrering skeleton movement. The LeapMotion device promises more and is probably the way to go for this, until a better, faster Kinect version arrives.

mandag den 29. april 2013

Javascript "static" class - make javascript code more readable


I usually use static classes for my C# helper-functions, when there're no properties to expose, nor any need to inherit from them. So this increases code readability. Javascript, however, doesn't have that feature, so how to immitate it? I usually do the below:



// declare object - recall that 'function' is an object in javascript
var WebServiceFunctions = function() {
}

// declare method on the object
WebServiceFunctions.webServiceMethod = function (parameter1, parameter2) {
// method code here

// return value if any
return xyz;
}


With the above code, I call my helper-method in my code like this:


var resultFromCall = WebServiceFunctions.webServiceMethod("foo","bar");


This has the odour of a static class. Of course behind the scene the "var WebServiceFunctions = function() {}" declaration signifies the creation of an object ("function" is an object in javascript), but I find that given the generic name - 'WebServiceFunctions' - my mind abstracts from this.

The javascript increases in readability, which may be an issue with a multitude of referenced javascript files.

There's a slightly better way, though. If the helper-functions are so generic in nature that they're applicable to many different purposes, they may be used in many different files. As such, the above will declare the "WebServiceFunctions"-object with every import of the javascript file. Better would be to check beforehand if the object has already been created, in which case there's no need to create it again:



(function () {
   
    this.WebServiceFunctions = this.WebServiceFunctions || {};

    
    var ns = this.WebServiceFunctions;

    ns.getMobilityPeriodId = function (serviceUrl) {
             // function code here
     }

})();



The above this.WebServiceFunctions = this.WebServiceFunctions || {}; is a conditional that checks if this.WebServiceFunctions has any value, in which case the already created object is returned, or - represented by the two pipes '||' - a new object is created. var ns is merely a reference, to avoid having to write 'this.WebServiceFunctions' repeatedly.

So that's a way to reference javascript in a 'namespace' sort of way. I find the above helps me keep my references handy and maintain the readability of my code, especially as a project starts to become clotted with javascript. If you wish to go depper into the subject matter, the above is what is known as the Javascript Module Pattern.

tirsdag den 16. april 2013

iTextSharp - multi-line form filling

For those of us using iTextSharp to generate dynamic PDF documents, one caveat I found was in controlling line breaks. In as much as the PDF standard has supported RTF since version 6.1, I was trying to add line breaks via RTF-code - "\par", i.e. Yet it turns out the iTextSharp parser appreciates the ever reliable System.Environment.Newline.

So format your PDF form field thus...:



... and you'll be able to reference your field and add line breaks thus:


PdfReader reader = null;
AcroFields af = null;

PdfStamper ps = null;

reader = new PdfReader(new RandomAccessFileOrArray(Request.MapPath(@"~/App_Data/your_pdf_document.pdf")), null);

ps = new PdfStamper(reader, stream);

AcroFields af = ps.AcroFields;

af.SetField("Your PDF form field name", @"This line is " + System.Environment.Newline + "broken");

// make resultant PDF read-only for end-user
ps.FormFlattening = true;

// forget to close() PdfStamper, you end up with
// a corrupted file!
ps.Close();


That's all there is to it.

Hope this helps you in your further career. And good luck with it, too!

Buy me a coffeeBuy me a coffee

mandag den 7. januar 2013

Modal detailsview


Simple tip, this,

if you're displaying an asp.net DetailsView on your aspx-page, you'll perhaps consider showing it with a modal-background so as to bring focus on it.

This is easily implemented by showing a hitherto hidden panel on the page. Here's the mark-up for that - put it at the very top of the page:




test



Then, in the code-behind code which shows the DetailsView, you'll include a bit of javascript (using Jquery here, but you don't have to) to show the hidden div:



newLanguageDetailsView.ChangeMode(DetailsViewMode.Insert);
detailsPanel.Visible = true;

System.Text.StringBuilder sbScript = new System.Text.StringBuilder("");

sbScript.Append("");

ScriptManager.RegisterStartupScript(this, this.GetType(), "@@@@MyPopUpScrip1t", sbScript.ToString(), false);



The only thing you'll need to remember to do is to add css to your DetailsView, to position it and add a z-index higher than the modalBackground, so it'll be presented above the gray full-screen background. So add this as the css-class attribute value for your DetailsView:

.zindexedDetailsview {
z-index: 100;
position: relative;
}


That's all there is to it. All other solutions I've seen include the Ajax framework and specifically the use of the ModalPopupExtender, so here's a lighter weighted alterantive.

Works for me with VS2012, .net 4.5, Jquery 1.8.3. Cheers!

tirsdag den 20. november 2012

WCF self-hosted Windows Workflow flowchart debugging


I'm looking into Microsoft Windows Workflow solutions - a really powerful tool, once you get the hang of it (it's a steep learning curve).

Testing a workflow is the easiest if you simply host the workflow within Visual Studio's own development web server. But I've found a debugging issue if you use a flowchart workflow as opposed to a sequential workflow.

In my case I was trying to step into a custom activity (a codeActivity), but no matter how I tried it, my breakpoints would not be hit. If I ran a sequential workflow, no problem, the breakpoints got hit.

The 'solution' was to simply start two instances of Visual Studio, load the solution into both and for the first one set the workflow project as the start-up project (and fire it up), and for the second one set the other project that's hitting the service (a console-application, in my case) and fire that one up. Having its own seperate managed instance ensured the workflow projects breakpoints were hit.

Another solution would be to add a 'Debugger.Break();'-statement, which would then, when hit, offer you a choice of debugging the solution. But it's far easier to just seperate the projects with two Visual Studio sessions.

HTH others.

fredag den 21. september 2012

jquery calendar appointment time picker


I was in need of a time picker with a corresponding duration-selector; and as I couldn't find anything which suited the requirements, I decided to make it myself. So here it is for you to grab if you like. This is what i looks like:



The requirement was to select a specific time on a time ruler, so I'm drawing a ruler on a html5 canvas element and, beneath it, a ruler to select the duration. With both rulers I overlay a 'ruler-marker' div, of course absolutely positioned, and those are decorated with the jquery UI 'draggable' attribute - limited in as much as you can only move the marker within the ruler. A 'onDrag'-handler makes sure the size of the ruler-marker of the time-ruler expands or contracts with the change in duration.

It's important to incorporate the touch-punch - http://touchpunch.furf.com/ - js support for the jquery ui, if you expect the draggable-functionality to work on IOS devices.

So that's a day's work for me, hopefully it'll save you one. Here's the source:

https://docs.google.com/open?id=0B8b-I3PiuN9lMlg2UnoxQnQ5MkU

Oh, there's a 'Helperfunctions.js' involved which I don't link to, but it incorporates a 'GetAbsolutePosition()'-function that I nicked from here: http://blogs.korzh.com/progtips/2008/05/28/absolute-coordinates-of-dom-element-within-document.html




onsdag den 19. september 2012

c# and Skype integration

UPDATE 7/9/13: I heard a rumor that Skype would no longer support the below method of integration. It's probably worth your while to check it out, and thus not waste your time if that's indeed the case.


I was asked to build a windows desktop application which offered video-assistances to students who visited with our physical helpdesk, only to find no-one there to help them - wherefore they could instead perform a video-call to the first available helpdesk-staffer.

My choice in building the application was to utilize the Skype API, in as much as the audio and video part is proven and reliable, and, well, there's no sense in re-inventing the wheel. They all use Skype to make intranet calls anyway, so they're used to it and very familiar with it. And so are the students, for that matter. So that's what I did and it worked out terrific. And here's how I did it:

1) You'll have to obtain a Skype licence. So go to http://developer.skype.com/ and join the developer program of your choice, either embedded or desktop. It's not a very costly program to join. This will get you your developer key. However, you'll download a *.pem-file, but in order to program against the Skype API on windows you'll need to convert this to a *.pfx file. No biggie: use this page - https://www.sslshopper.com/ssl-converter.html - to do an online conversion, which will result in a pfx-file you can import into your c# project, as did I. P.S.: the online conversion page will have you select both a 'Private Key File:' and a 'Certificate File to Convert:'. In both fields provide your downloaded *.pem file.

2) So you've got your *.pfx licence-file now, and the next thing you'll need is the SkypeKit_VS2010.dll so you can program against the API. Specifically you'll want to download the SkypeKit version 4.3.1 - here it is: http://developer.skype.com/skypekit/releases/skypekit-4-3-hf1/release_files/skypekit/downloads/101904 (desktop version). The gz-file you'll download via the above link contains a Visual Studio 2008 and 2010 project alike, and when you build that you get the dll as a result. Alternatively you can download my source code, the Visual Studio 2010 version of the dll is in there. I do recommend download the above kit, though, there's some great example code for your perusal.

2.5) Download the Skype runtime exe-file. The api-calls you make will be executed against this runtime exe-file. The exe is in the SkypeKit you downloaded - or you can browse the 'dll'-folder in my source code and the windows x86 exe is in there. 3) You've got your licence key and your dll. Reference the dll in your project and you'll be ready to program against the API. You'll do the following:

a) reference your licence key, like this: X509Certificate2 cert = new X509Certificate2(@"C:\userprofiles\mno\My Documents\Visual Studio 2010\Projects\SkypeTest\SkypeTest\SkypeStuff\Version.pfx", @"wallen11");

b) initiate a new Skype API connection: skype = new SktSkype(this, cert, true, false, 8963);

c) declare the 'onConnect' event handler associated with the skype API connection you've just initialized. This connect-handler will handle login via your account. skype.events.OnConnect += OnConnect;

d) Launch the Skype runtime. Again, this runtime receives the commands you send to the Skype API and executes them. skype.LaunchRuntime(@"C:\yourPathToTheExe\windows-x86-skypekit.exe", true);

e) ... And connect: skype.Connect();

f) The connect-command will trigger the onConnect-handler, which takes care of our logging into Skype:

public void OnConnect(object sender, SktEvents.OnConnectArgs e)
{
if (e.success)
{
account = skype.GetAccount();
account.LoginWithPassword(, false, false);
}
else
{
throw new Exception("IPC handshake failed with: " + e.handshakeResult + "\r\n");
}
}

4) Let's assume you've got connected to Skype, i.e. your desktop application is connected to the Skype network. Now it's a matter of making a call from the desktop application. This is where it gets a bit tricky. Your only - for now - option in calling other Skype contacts is to emulate a previous conversation you've had with them. You can do something akin 'SkypeCall call = new SkypeCall("SkypeAccountIWantToCall"); call.Ring();'.

What you must do is first get a list of your account's previous conversations:

conversationList = skype.GetConversationList(SktConversation.LIST_TYPE.ALL_CONVERSATIONS);

... and from one of those conversations you'll retrieve the list of participants:

SktParticipant.List parts = selectedConversation.GetParticipants(SktConversation.PARTICIPANTFILTER.OTHER_CONSUMERS);
List names = new List();
foreach (SktParticipant part in parts)
{
names.Add(part.P_IDENTITY);
}

// call the contact
conv.RingOthers(names, true, "");

There's a bit more to it than that - such as handling video, and checking for contact availability. I'll refer to my sample code. What I do is this, I get a list of the previous conversation and sort through these. I add the conversations by distinct users to an invisible listbox. A 'call' button traverses the conversations and checks availability of the participants; first available helpdesk employee gets the honors. That's perhaps not the most elegant fashion, the invisible listbox-thing, in my defence I was in a hurry and leaned heavily on the tutorial code provided by Skype.

As always here's a link to the source code of my effort:

https://docs.google.com/open?id=0B8b-I3PiuN9lMXNkTllyU1dGVms

Not documented terribly well, but, as always, get back to me if there's anything I can explain better, or if you need help in general.

Hope it helps! Best of luck in your coding efforts.

tirsdag den 10. juli 2012

Editing PDF form on the web

I was asked to make a PDF form editable on the web. The HR department already had the form, now they wanted me to make it editable via an url.

The solution involves

- setting up a database to hold the PDF form data,
- making the PDF form submittable to a web page,
- utilizing the iTextSharp-library to parse the submitted PDF form

Setting up the database involves creating a table with columns for every field in the PDF-form you need stored - likely all of them. Also there must be a primary key in the form of an auto-incremented value or a global unique identifier. Having set up the database, allow the PDF form to be submittable to a web page. In Adobe Acrobat Pro, go to the "Forms -> Add or Edit Fields" and add a PDF button with the text "save" on it. Define a button action for the mouse-up event; specifically, a "submit form" action (*). The properties for the action should look akin to this:

















*) I'm using a Danish version of Acrobat Pro, so the menus and texts may slightly different from the above.

I.e. the form submits into a generic handler "pdfHandler.ashx" when it is clicked (the mouse-down action). The handler's default "ProcessRequest" function looks like this:


---

 public void ProcessRequest(HttpContext context)
        {

            HttpRequest pdfRequest = HttpContext.Current.Request;
            System.IO.Stream istream = HttpContext.Current.Request.InputStream;
            FdfReader fdf = new FdfReader(istream);

            // eksisterende?
            if (!string.IsNullOrEmpty(fdf.GetFieldValue("ident")))
            {
                DataClassesDataContext dbContext = new DataClassesDataContext();

                int id = Convert.ToInt32(fdf.GetFieldValue("ident"));
             
                lejere lejer = dbContext.lejeres.Single(foo => foo.id.Equals(id));
                lejer.ad1 = fdf.GetFieldValue("ad1") == null ? string.Empty : fdf.GetFieldValue("ad1").ToString();
                // populate all database object properties
         
                dbContext.SubmitChanges();
            }
            else
            {
                #region new lejer

                try
                {
                    DataClassesDataContext dbContext = new DataClassesDataContext();
                    lejere lejer = new lejere()
                    {
                        ad1 = fdf.GetFieldValue("ad1") == null ? string.Empty : fdf.GetFieldValue("ad1").ToString(),
                        ad2 = fdf.GetFieldValue("ad2") == null ? string.Empty : fdf.GetFieldValue("ad2").ToString(),
                        // populate all database object properties
                    };

                    if (string.IsNullOrEmpty(fdf.GetFieldValue("lejernavn1")) && string.IsNullOrEmpty(fdf.GetFieldValue("lejernavn2")))
                    {
                        lejer.lejernavn1 = "Uudfyldt";
                        lejer.lejernavn2 = "Uudfyldt";
                    }
                    dbContext.lejeres.InsertOnSubmit(lejer);
                    dbContext.SubmitChanges();
                }
                catch (Exception ex)
                {
                    throw ex;
                }

                #endregion
            }

            HttpContext.Current.Response.Redirect("Default.aspx", true);
        }
---


Basically what takes place here, is that an iTextSharp pdf-reader is instantiated from a HTTPRequest which is the submitted PDF document. Using LINQ to SQL, a database object corresponding to the PDF form (recall we just created the database and its table with columns for all the PDF form fields) is populated from the PDF form (the 'GetFieldValue' function of the iTextSharp library) and stored to the database via LINQ to SQL. 


The "New" option is relatively straight forward, in as much as the LINQ to SQL functionality itself works out to insert a new auto incremented integer primary key, if you're - as am I in this case - going with auto-integers for database keys. The "Edit" option is more of a challenge - here we'll have to inject the primary key into the PDF form, before allowing the generic handler to take over and grap this value when the form is submitted. The way to do this is so:


In the edit-button click function, do this:


---

 int lejerId = Convert.ToInt32(LejereDropDown.SelectedValue);
                DAL.lejere lejer = dbContext.lejeres.Single(foo => foo.id.Equals(lejerId));

                PdfReader reader = null;
                AcroFields af = null;

                PdfStamper ps = GetPDFFields(ref reader, ref af);

                SetFormData(ref af, lejer);

                // forget to close() PdfStamper, you end up with
                // a corrupted file!
                ps.Close();
             
                if (reader != null)
                {
                    Response.AddHeader("Content-Disposition", "inline;filename=lejekontrakt.pdf");
                    Response.ContentType = "application/pdf";
                }


What happens here is that we instantiate an iTextSharp PDF-reader and use the "GETPDFField"-method to achieve a reference to all the form fields in this PDF. THe "SetFormData" function simply fills in these form fields (like so;  "af.SetField("ident", lejer.id.ToString());") - including a hidden "ident" field on the form. Once the form fields have been populated, we'll redirect into the form by changing the page headers and response contenttype, as written.

Hope the above helps! All the references to 'fields', 'forms' and such can get confusing, so be sure to get in touch with me if anything needs explaining further.

mandag den 4. juni 2012

Live c# video streaming webcam server and client

I wanted to capture live video from a webcam and stream it directly to a client application. This was thought to be for a robot which would stream video from its webcam eyes and allow me to see what the robot sees, but really it would be possible to build a cheap DIY home surveillance network around this.

The VS 2010 c# solution holds two projects, one commandline project for the server and one windows forms project for the client.

The server stream not video, but rather a series of captures images, but in presenting these images in a rapid fashion the end result will seem like a naturally flowing video stream. The images  made available to a connecting client IP by an initialized WCF service, namely via a tcp/ip binding. The images capture is done by utilizing the AForge framework to access an available webcam. The images are saved to disk and not to memory, as I wanted to retain the option of going through them again at a later point. The last captured image is always kept in memory, to be delivered to the calling client as the WCF's 'getWebCamImage()' method is invoked.

I set the web cam framerate to 15 frames per second, which is fine enough to moving images. The maximum number of images the human eye can distinguish is 30 per second, so I'm told, so 15 images per second makes for a comfortably video experience.

The client creates an instance of the WCF service. A timer is set to call the service and return an image-stream, which is placed into a standard winforms picturebox. In the example code the timer is set at 100 milliseconds, which will yield only 10 images per second - thus not the 15 frames which are actually captured, I did this to perserve bandwidth but in reality it should be perfectly possible to call the timer 15 times per second. The viewing experience is nice enough just the same.

Check out the source code below if you're in need of something like this. Please bear with all the references to 'robot this' and 'robot that', the functionality was meant for a robot control project. The WCF service runs localhost, but you would of course in due time seperate the client from the server and allow the service to run via an external IP, firewall-configured to the port of your choice and not my standard port no 8733.

Link to solution source code

Let me know if there's anything I can do to help you in implementing the project, if it gives you any trouble.

Hope this helps you!

Buy me a coffeeBuy me a coffee