Render in MVC a link with image and text

Hi guys, I want in MVC to render a text with an image as an ActionLink. For creating a simple anchor tag, we use Html.ActionLink() helper which generates anchor tag for us.

If you want to create something a bit more complicated, you must create you own component. For this reason, I created the following code. It allows you to create an anchor with an image and a text.

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

namespace PSC.MVC.Helpers
{
    public static class CustomHtmlHelpers
    {
        /// 
        /// Enum ImageAndText
        /// 
        public enum ImageAndText
        {
            /// 
            /// Image on the left, text on the right
            /// 
            ImageOnTheLeft,

            /// 
            /// Text on the left, image on the right
            /// 
            ImageOnTheRight
        }

        /// 
        /// Images the action link.
        /// 
        /// The HTML helper.
        /// The link text.
        /// The action.
        /// The controller.
        /// The route values.
        /// The HTML attributes.
        /// The image source.
        /// The alternate text.
        /// The text style.
        /// The image style.
        /// The image position.
        /// IHtmlString.
        public static IHtmlString ImageActionLink(
               this HtmlHelper htmlHelper, string linkText, string action, 
               string controller, object routeValues, object htmlAttributes, 
               string imageSrc, string alternateText = "", 
               string textStyle = "", string imageStyle = "", 
               ImageAndText imagePosition = ImageAndText.ImageOnTheLeft)
        {
            var urlHelper = new UrlHelper(
                    htmlHelper.ViewContext.RequestContext);

            // create the image
            var img = new TagBuilder("img");
            img.Attributes.Add("src", 
                    VirtualPathUtility.ToAbsolute(imageSrc));
            if (!string.IsNullOrEmpty(alternateText))
                img.Attributes.Add("alt", alternateText.Trim());
            if (!string.IsNullOrEmpty(imageStyle))
                img.Attributes.Add("style", imageStyle);

            // create a render for the image and the text
            string render = "";
            if (imagePosition == ImageAndText.ImageOnTheLeft)
                render = img.ToString(TagRenderMode.SelfClosing) + linkText;
            else
                render = linkText + img.ToString(TagRenderMode.SelfClosing);

            // create the anchor with image and text
            var anchor = new TagBuilder("a") {
                InnerHtml = render
            };
            if (!string.IsNullOrEmpty(textStyle))
                anchor.AddCssClass(textStyle);

            // add reference to the anchor
            anchor.Attributes["href"] = urlHelper.Action(action, 
                                                         controller, 
                                                         routeValues);
            anchor.MergeAttributes(new RouteValueDictionary(htmlAttributes));

            return MvcHtmlString.Create(anchor.ToString());
        }
    }
}

In your MVC code you have to add:

@using PSC.MVC.Helpers;

and then you can call your component:
@Html.ImageActionLink("Your text", "Index", "Home", null, null, 
                      "~/Content/images/img.png", "Logo", "navbar-brand", 
                      "width: 40px;")

A Simple Speedtest Application for Xamarin

In my previous post I described how to check your connection in a C# project. I should have the same function in a PCL project for Xamarin. Based on my project, I created this function:
using System;
using System.Net.Http;
using System.Threading.Tasks;

namespace PSC.Xamarin.Connection
{
	/// 
	/// Speed test.
	/// 
	public class SpeedTest
	{
		public double SecondsForOneMb { get; set; } = 0;
		public double KbSeconds { get; set; } = 0;

		/// 
		/// Starts the test to download a file from an url.
		/// Read SecondsForOneMb and KbSeconds for the result
		/// 
		public async Task StartTest()
		{
			string url = 
            "http://puresourcecode.com/file.axd?file=/SpeedTest/1024kb.txt";
			HttpClient client = new HttpClient();

			// get current tickcount 
			double starttime = Environment.TickCount;

			// download file from the specified URL, 
			// and save it to C:\speedtest.txt
			// in your project change the path of the following line
			var httpResponse = await client.GetAsync(url);
			byte[] dataBuffer = 
                   await httpResponse.Content.ReadAsByteArrayAsync();

			// get current tickcount
			double endtime = Environment.TickCount;

			// how many seconds did it take?
			// we are calculating this by subtracting starttime from
			// endtime and dividing by 1000 (since the tickcount is in 
			// miliseconds 1000 ms = 1 sec)
			SecondsForOneMb = Math.Floor(endtime - starttime) / 1000;

			// calculate download rate in kb per sec.
			// this is done by dividing 1024 by the number of seconds it
			// took to download the file (1024 bytes = 1 kilobyte)
			KbSeconds = Math.Round(1024 / SecondsForOneMb);
		}
	}
}

Happy coding!

A Simple Speedtest Application

The purpose of this code is the detect how slow is your connection downloading a file from a site. First of all, you have to create a file with a known size: for that you can use fsutil in the prompt (see another post in this blog for info).

When yo do put your file in a webserver (or you can use my url), we can create the code to check the connection speed.

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;

namespace SpeedTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Title = "A simple speed test connection for your app";

            // the URL to download a file from
            Uri URL = new Uri(
            "http://puresourcecode.com/file.axd?file=/SpeedTest/1024kb.txt"
            );
            WebClient wc = new WebClient();

            Console.WriteLine("Simple speedtest");
            Console.WriteLine("----------------");
            Console.WriteLine("Will test your download rate. " + 
                              "Press any key to begin.");
            Console.ReadKey();

            Console.WriteLine("\nDownloading file: 1024kb.txt...");
            Console.WriteLine("From http://puresourcecode.com");
            Console.WriteLine("Note: This file will automatically " + 
                              "be deleted after the test.");

            // get current tickcount 
            double starttime = Environment.TickCount;

            // download file from the specified URL, 
            // and save it to C:\speedtest.txt
            // in your project change the path of the following line
            wc.DownloadFile(URL, @"C:\speedtest.txt");

            // get current tickcount
            double endtime = Environment.TickCount;

            // how many seconds did it take?
            // we are calculating this by subtracting starttime from
            // endtime and dividing by 1000 (since the tickcount is in 
            // miliseconds 1000 ms = 1 sec)
            double secs = Math.Floor(endtime - starttime) / 1000;

            // calculate download rate in kb per sec.
            // this is done by dividing 1024 by the number of seconds it
            // took to download the file (1024 bytes = 1 kilobyte)
            double kbsec = Math.Round(1024 / secs);

            Console.WriteLine("\nCompleted. Statistics:\n");

            Console.WriteLine("1mb download: \t{0} secs", secs);
            Console.WriteLine("Download rate: \t{0} kb/sec", kbsec);

            Console.WriteLine("\nPress any key to exit...");
            Console.Read();
            Console.WriteLine("Deleting file...");
            try
            {
                // delete downloaded file
                System.IO.File.Delete(@"C:\speedtest.txt");
                Console.WriteLine("Done.");
            }
            catch
            {
                Console.WriteLine("Couldn't delete download file.");
                Console.WriteLine("To delete the file yourself.");
                Console.ReadKey();
            }
        }

    }
}

Happy coding!

Xamarin forms, UWP Windows 10 App, TitleBar and Status bar customization

Customize the title bar of your Universal App for Windows 10 is quite easy, but you need to write different code for PC and Mobile. The class that allows you to customize the title bar:

  • when running on a PC is called TitleBar
  • when running on a Mobile is called StatusBar

Before to call the API you first need to check if it exists (true if you are running on that platform):

//PC customization
if (ApiInformation.IsTypePresent(
                   "Windows.UI.ViewManagement.ApplicationView"))
{
    var titleBar = ApplicationView.GetForCurrentView().TitleBar;
    if (titleBar != null)
    {
        titleBar.ButtonBackgroundColor = Colors.DarkBlue;
        titleBar.ButtonForegroundColor = Colors.White;
        titleBar.BackgroundColor = Colors.Blue;
        titleBar.ForegroundColor = Colors.White;
    }
 }

//Mobile customization
if (ApiInformation.IsTypePresent("Windows.UI.ViewManagement.StatusBar"))
{

    var statusBar = StatusBar.GetForCurrentView();
    if (statusBar != null)
    {
        statusBar.BackgroundOpacity = 1;
        statusBar.BackgroundColor = Colors.DarkBlue;
        statusBar.ForegroundColor = Colors.White;
    }
}

You could receive an error

StatusBar doesn't exist in context

You resolve it to add in the reference for UWP project Windows Mobile Extensions for the UWP and Windows Desktop Extensions for the UWP.

Extensions

Happy coding!

Add Calabash to your Xamarin project

Why add Calabash to your project? Because without it you can't test your application with Xamarin Test Cloud.

Scenario

I created my app for iOS and I want to test it on Xamarin Cloud. First thing I have to install to create a UITest easily is Xamarin Test Recorder. When I opened this application, I was confuse because nobody explain what kind of app I can choose. Basically if you have a iOS project, before use Xamarin Test Recorder, you must create an .ipa and it means you have to create an archive and publish it.

After createing a UITest project you can sent it with Export function directly to TestCloud. The problem I discovered is

Errors and Failures:
1) SetUp Error : RecorderTest.NewTest
   SetUp : System.Exception : Unable to contact test backend running in app. A common cause is that the app is not properly linked with Calabash. Please verify that it includes the Calabash component.
  at Xamarin.UITest.iOS.iOSAppLauncher.EnsureCalabashRunning (ICalabashConnection connection) <0x7507b30 + 0x0005f> in <filename unknown>:0 
  at Xamarin.UITest.iOS.iOSAppLauncher.LaunchApp (IiOSAppConfiguration appConfiguration, Xamarin.UITest.Shared.Http.HttpClient httpClient, Xamarin.UITest.TestCloud.TestCloudiOSAppConfiguration testCloudAppConfiguration, Xamarin.UITest.Shared.Http.HttpClient testCloudWsClient, Xamarin.UITest.Shared.Http.HttpClient xtcServicesClient, Boolean testCloudUseDeviceAgent) <0x6cbb340 + 0x0019b> in <filename unknown>:0 
  at Xamarin.UITest.iOS.iOSApp..ctor (IiOSAppConfiguration appConfiguration, IExecutor executor) <0x6b39778 + 0x00b03> in <filename unknown>:0 
  at Xamarin.UITest.iOS.iOSApp..ctor (IiOSAppConfiguration appConfiguration) <0x6b39738 + 0x0001f> in <filename unknown>:0 
  at Xamarin.UITest.Configuration.iOSAppConfigurator.StartApp (AppDataMode appDataMode) <0x6b38e18 + 0x00063> in <filename unknown>:0 
  at RecorderTest.SetUp () <0x6b37f70 + 0x0004f> in <filename unknown>:0 
  at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&)
  at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) <0x31e7110 + 0x00093> in <filename unknown>:0 

Why this? Because I didn't install Calabash.

Add Calabash for iOS

First al all, open your Terminal with admin privileges. Then execute this script:

gem install calabash-cucumber gem install calabash-android gem install xamarin-test-cloud

Now in your system there are the basic for Calabash.

Now you can install a Calabash sandbox. Do not use sudo to install the Calabash Sandbox. Execute this script

curl -sSL https://raw.githubusercontent.com/calabash/install/master/install-osx.sh | bash

Now in the directory of your iOS project execute this script:

calabash-ios download

And finally you can generate a feature folder. The features folder is a special folder where Cucumber expects the test code to reside. Calabash can create this folder and provide some boilerplate code to get us started.

The last step is to execute in your iOS project the following command in the Terminal

calabash-ios gen

Now you create a new .ipa and do a new test. This time it will work!

Happy coding!

An error occurs with MobileCenter for Xamarin iOS

I added Microsoft Mobile Center to my project after creating the app there. On MobileCenter documentation you can know the Install Identifier for your application (MobileCenter documentation is here).

System.Guid installId = MobileCenter.InstallId;

This function is working fine if you have Android or iOS 10. With iOS less than 10 an error occurs:

Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).

and the StackTrace is similar to

at System.Guid+GuidResult.SetFailure (System.Guid+ParseFailureKind failure, System.String failureMessageID, System.Object failureMessageFormatArgument, System.String failureArgumentName, System.Exception innerException) [0x00030] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.123/src/mono/mcs/class/referencesource/mscorlib/system/guid.cs:198 \n at System.Guid+GuidResult.SetFailure (System.Guid+ParseFailureKind failure, System.String failureMessageID) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.123/src/mono/mcs/class/referencesource/mscorlib/system/guid.cs:184 \n at System.Guid.TryParseGuidWithDashes (System.String guidString, System.Guid+GuidResult& result) [0x0008f] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.123/src/mono/mcs/class/referencesource/mscorlib/system/guid.cs:695 \n at System.Guid.TryParseGuid (System.String g, System.Guid+GuidStyles flags, System.Guid+GuidResult& result) [0x00115] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.123/src/mono/mcs/class/referencesource/mscorlib/system/guid.cs:443 \n at System.Guid.Parse (System.String input) [0x00021] in /Library/Frameworks/Xamarin.iOS.framework/Versions/10.4.0.123/src/mono/mcs/class/referencesource/mscorlib/system/guid.cs:262 \n at Microsoft.Azure.Mobile.MobileCenter.get_InstallId () [0x0000a] in :0 \n at myInventories.Helpers.LogHelpers.SendMessageToAzure (System.String EventName, System.String PageName, System.String BaseClass, myInventories.Logs.ActionType Action, System.String MoreInfo, System.Collections.Generic.Dictionary`2[TKey,TValue] DictionaryInfo) [0x00008] in /Users/enricorossini/Projects/myInventories/myInventories/myInventories/Helpers/LogHelpers.cs:72

To avoid this error you have to check the OS version.

Implementation

In your solution you have to add in all projects Device Information Plugin (for NuGet Xam.Plugin.DeviceInfo). Then you check easily the OS version with

// check the OS version to avoid error on MobileCenter
string MobileId = "";
var osInfo = CrossDeviceInfo.Current;
if ((osInfo.Platform == Plugin.DeviceInfo.Abstractions.Platform.iOS) && 
    (osInfo.VersionNumber.Major < 10)) 
{
    MobileId = "Unknown";
}
else {
    MobileId = MobileCenter.InstallId.ToString();
}

Happy coding!

Happy 15th Birthday .NET!

Happy-Birthday-Microsoft-DotNet

Today marks the 15th anniversary since .NET debuted to the world. On February 13th, 2002, the first version of .NET was released as part of Visual Studio.NET. It seems just like yesterday when Microsoft was building its “Next Generation Windows Services” and unleashed a new level of productivity with Visual Studio.NET.

Since the beginning, the .NET platform has allowed developers to quickly build and deploy robust applications, starting with Windows desktop and web server applications in 2002. You got an entire managed framework for building distributed Windows applications, ASP.NET was introduced as the next generation Active Server Pages for web-based development, and a new language, C# (pronounced “see sharp” :-)) came to be.

Over the years, .NET and it’s ecosystem has grown and expanded to meet the needs of all kinds of developers and platforms. As the technology landscape has changed, so has .NET. You can build anything with .NET including cross-platform web apps, cloud services, mobile device apps, games and so much more. We have a vibrant open-source community where you can participate in the direction of .NET.

Xamarin.Forms (Android): Workaround For Splash Screen With Logo

What is the quickest way to add a splash screen to your Android project in Xamarin?

  1. Create a new folder under the Android project folder "Resources" with the name "Values".
  2. In that folder add a new "Styles.xml" file. Add -> New Item, then XML File. Make sure after creating this file to have the property "Build Action" set to the default value: "AndroidResource". In this file we will create a new theme "Theme.Splash" that set the background of our Splash with our logo.
  3. Edit the file to be as follows:
    <?xml version="1.0" encoding="utf-8" ?>
    <resources>
      <style name="Theme.Splash" parent="android:Theme">
        <item name="android:windowBackground">@drawable/myLogo</item>
        <item name="android:windowNoTitle">true</item>
      </style>
    </resources>
  4. Add a Splash Activity to the Android Project using Add -> New Item, then Activity. Let's name it SplashActivity.
  5. Change the attributes of the activity to set the theme attribute to "@styles/Theme.Splash", MainLauncher attribute to "True", and NoHistory also to "True". The Theme attribute is responsible for the style of the activity, the MainLauncher is responsible for making this activity the first activity to show and NoHistory is responsible for preventing navigation back to this activity. The activity attributes should look like the following:
    [Activity(Theme = "@style/Theme.Splash", 
              MainLauncher = true, 
              NoHistory = true)]
  6. Add the following code to the "OnCreate" method in Splash activity immediately after the comments // Create your application here:
    // Simulate a long loading process on app
    System.Threading.Thread.Sleep(10000);
    StartActivity(typeof(MainActivity));

    The first line simulates a long-loading process.
    The second line Start our MainActivity where our application will run main tasks after the Splash is shown.

  7. Just before running the application, we need to ensure that the MainLancher attribute of the MainActivity is set to false:
    [Activity(Label = "HandyApp.Droid", Icon = "@drawable/icon", 
              MainLauncher = false, 
              ConfigurationChanges = ConfigChanges.ScreenSize | 
                                     ConfigChanges.Orientation)]
  8. And let's run the application.

Do you want to logo in the center of your screen?

  1. In Styles.xml, remove the entire line where the "windowBackground" attribute and value are. Instead insert the following line specifying that the background is of White color:
    <item name="android:colorBackground">@android:color/white</item> 
  2. In the Resources folder, create a new folder "layout". Here we will add our layout for the SplashActivity.
  3. In the layout folder, add a new Android Layout: Add->New Item...->Android Layout. let's call it "SplashLayout.xaml".
  4. Edit the source of SplashLayout to match the following markup:
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:minHeight="25px"
        android:minWidth="25px"
        android:gravity="center"
        android:background="#6d6763">
        <ImageView
            android:src="@drawable/myLogo"
            android:layout_height="fill_parent"
            android:layout_width="wrap_content"
            android:layout_gravity="center"
            android:id="@+id/imageView1" />
    </LinearLayout>
    Here we have an ImageView in the center with source (src) of your logo in the drawable folder.
  5. In SplashActivity.cs, edit the "OnCreate" method to match the following code:
    [Activity(Theme = "@style/Theme.Splash", 
              MainLauncher = true, NoHistory = true)]
    public class SplashActivity : Activity {
        protected override void OnCreate(Bundle savedInstanceState) {
            base.OnCreate(savedInstanceState);
    
            SetContentView(Resource.Layout.SplashLayout);
            System.Threading.ThreadPool
                            .QueueUserWorkItem(o => LoadActivity());
        }
    }
    In this code, we set the content view of the SplashActivity to our SplashLayout.xaml and then we queue the MainActivity in the ThreadPool object using the LoadActivity method that we will write in the next step.
  6. Add a new method to the SplashActivity class called "LoadActivity":
    private void LoadActivity()     {
        // Simulate a long pause
        System.Threading.Thread.Sleep(5000);
        RunOnUiThread(() => StartActivity(typeof(MainActivity)));
    }  
    Note how we shifted the sleep period to this method.
  7. Run the application

C# IL Viewer for Visual Studio Code using Roslyn side project

For the past couple of weeks I've been working on an IL (Intermediate Language) Viewer for Visual Studio Code. As someone that develops on a Mac, I spend a lot of time doing C# in VS Code or JetBrains' Rider editor - however neither of them have the ability to view the IL generated (I know JetBrains are working on this for Rider) so I set out to fix this problem as a side project.

As someone that's never written a Visual Studio Code extension before it was a bit of an abmitious first extension, but enjoyable none the less.

Today I released the first version of the IL Viewer (0.0.1) to the Visual Studio Code Marketplace so it's available to download and try via the link below:

Download IL Viewer for Visual Studio Code

Download C# IL Viewer for Visual Studio Code or install it directly within Visual Studio Code by launching Quick Open (CMD+P for Mac or CTRL+P for Windows) and pasting in the follow command and press enter.

ext install vscodeilviewer

The source code is all up on GitHub so feel free to take a look, but be warned - it's a little messy right now as it was hacked together to get it working.

il_viewer_animated

For more information you can visit this link.

Global Resources problem in Xamarin projects

Today I spent a lot of time to understand why my style doesn’t work.

<Application xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             x:Class="myProject.App">
    <Application.Resources>
        <ResourceDictionary>
            <Style x:Key="WarmGreyLine" TargetType="BoxView">
                <Setter Property="HeightRequest" Value="1" />
                <Setter Property="HorizontalOptions" Value="Fill" />
                <Setter Property="Color" Value="#EEE9E5" />
                <Setter Property="Margin" Value="0,10,0,10" />
            </Style>
        </ResourceDictionary>
    </Application.Resources>
</Application>

I followed a video about it on Xamarin University. Everything was the same. They say you can copy your style from a ContentPage.Resources and page in the Application.Resources section

    <ContentPage.Resources>
        <ResourceDictionary>
            <Style x:Key="WarmGreyLine" TargetType="BoxView">
                <Setter Property="HeightRequest" Value="1" />
                <Setter Property="HorizontalOptions" Value="Fill" />
                <Setter Property="Color" Value="#EEE9E5" />
                <Setter Property="Margin" Value="0,10,0,10" />
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>

The XAML is correct but if you execute the code you receive an error like:

Inner Exception: Position 38:14. StaticResource not found for key WarmGreyLine Message: Exception has been thrown by the target of an invocation.

The Solution

The is a little thing in the video they forgot to say!

In the App.xaml.cs you have to call InitializeComponent();

namespace myInventories
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
        }
    }
} 

Happy coding!

Advertsing

125X125_06





TagCloud

MonthList

CommentList