Snippet – Post form data with file using jQuery

HTML:

<form id="userForm">
    <div>
      <label>First Name: </label>
      <input type="text" name="firstName" />
    </div>
    <div>
      <label>Last Name: </label>
      <input type="text" name="lastName" />
    </div>
    <div>
      <label>Image: </label>
      <input type="file" name="image" />
    </div>
    <input type="submit" value="Submit"/>
</form>

Javascript:

$(function () {
    $("#userForm").on("submit", function(e) {
      
      var form = document.querySelector("#userForm");
      var formData = new FormData(form);
      
      /* ANOTHER WAY
      var formData = new FormData(this);
      */
      
      // Add extra information in form data
      formData.append("isActive","true");
      
      var url = "http://localhost:8080/user";
      
      $.ajax({
        url: url,
        data: formData,
        type: "POST",
        processData: false,
        contentType: false
      }).done(function(response) {
        // success
      }).fail(function(error) {
        // fail
      });
    });
});

Create Simple Expander Control in Xamarin Forms

In this post, we will be creating a simple expander control which will contain a header and content view, and provide a way to expand and collapse content view by tapping on the header.

So here is the design for custom Expander control.

Open Visual Studio and create new empty Xamarin Forms project.

Add new Content View file in the project and named as “CustomExpander”.

Add Frame in CustomExpander.xaml file with CornerRadius=5 to give rounder corners.

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="CustomExpanderView.CustomExpander">

    <Frame CornerRadius="5"
           BorderColor="#E1E1E1"
           BackgroundColor="#FFFFFF"
           HasShadow="False"
           Padding="0">

        <!-- HEADER & CONTENT VIEW -->
        
    </Frame>
</ContentView>

Basic Control Layout

<Grid>
    <Grid.RowDefinitions>
        <!-- Header View -->
        <RowDefinition Height="Auto"/>
        <!-- Content View -->
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
</Grid>

CustomExpander.xaml

<Frame CornerRadius="5"
       BorderColor="#E1E1E1"
       BackgroundColor="#FFFFFF"
       HasShadow="False"
       Padding="0">

    <Grid RowSpacing="0">
        <Grid.RowDefinitions>
            <!-- Header View -->
            <RowDefinition Height="Auto" />
            <!-- Content View -->
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Grid Grid.Row="0"
              Padding="8,6"
              BackgroundColor="#F5F5F5">
            <Label Text="{Binding Title}"
                   VerticalOptions="Center"
                   FontSize="14" />
            <Image HorizontalOptions="End"
                   VerticalOptions="Center"
                   HeightRequest="14">
                <Image.Source>
                    <FileImageSource File="{Binding ExpandIcon}" />
                </Image.Source>
            </Image>

            <Grid.GestureRecognizers>
                <TapGestureRecognizer Tapped="HeaderContent_OnTapped"
                                      NumberOfTapsRequired="1" />
            </Grid.GestureRecognizers>

        </Grid>

        <!-- Header Bottom Border -->
        <BoxView Grid.Row="0"
                 Color="#EBEBEB"
                 HeightRequest="1"
                 Opacity="0.8"
                 VerticalOptions="End"
                 HorizontalOptions="FillAndExpand"
                 IsVisible="{Binding IsExpanded}" />

        <!-- Content View -->
        <ContentView Grid.Row="1"
                     x:Name="BodyContentView"
                     Padding="8,6"
                     IsVisible="False" />
    </Grid>
</Frame>

CustomExpander.xaml.cs

using System;
using Xamarin.Forms;

namespace CustomExpanderView
{
    public partial class CustomExpander : ContentView
    {
        private static readonly string ArrowDown = "arrowhead-down.png";
        private static readonly string ArrowUp = "arrowhead-up.png";

        private string _expandIcon;

        public static readonly BindableProperty IsExpandedProperty =
            BindableProperty.CreateAttached(nameof(IsExpanded),
                typeof(bool),
                typeof(CustomExpander),
                false,
                BindingMode.TwoWay);

        public static readonly BindableProperty TitleProperty =
            BindableProperty.CreateAttached(nameof(Title),
                typeof(string),
                typeof(CustomExpander),
                string.Empty);


        public static readonly BindableProperty BodyContentTemplateProperty =
            BindableProperty.CreateAttached(nameof(BodyContentTemplate),
                typeof(DataTemplate),
                typeof(CustomExpander),
                null,
                BindingMode.TwoWay,
                propertyChanged: ContentBodyTemplatePropertyChanged);

        public string Title
        {
            get => (string)GetValue(TitleProperty);
            set => SetValue(TitleProperty, value);
        }

        public bool IsExpanded
        {
            get => (bool)GetValue(IsExpandedProperty);
            set => SetValue(IsExpandedProperty, value);
        }

        public DataTemplate BodyContentTemplate
        {
            get => (DataTemplate)GetValue(BodyContentTemplateProperty);
            set => SetValue(BodyContentTemplateProperty, value);
        }

        public string ExpandIcon
        {
            get => _expandIcon;
            set
            {
                _expandIcon = value;
                OnPropertyChanged(nameof(ExpandIcon));
            }
        }

        public CustomExpander()
        {
            InitializeComponent();
            Init();
            BindingContext = this;
        }

        private void Init()
        {
            ExpandIcon = ArrowDown;
            BodyContentView.IsVisible = false;
        }

        private static void ContentBodyTemplatePropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
        {
            var cp = (CustomExpander)bindable;

            var template = cp.BodyContentTemplate;
            if (template != null)
            {
                var content = (View)template.CreateContent();
                cp.BodyContentView.Content = content;
            }
            else
            {
                cp.BodyContentView.Content = null;
            }
        }

        private void HeaderContent_OnTapped(object sender, EventArgs e)
        {
            if (!IsExpanded)
            {
                BodyContentView.Opacity = 0;
            }

            IsExpanded = !IsExpanded;
            ExpandIcon = IsExpanded ? ArrowUp : ArrowDown;

            BodyContentView.IsVisible = IsExpanded;
            BodyContentView.FadeTo(1, 400, Easing.SpringOut);
        }
    }
}

How to use CustomExpander control?

<customExpanderView:CustomExpander Title="Items">
    <customExpanderView:CustomExpander.BodyContentTemplate>
        <DataTemplate>
            <StackLayout>
                <Label Text="Item 1"></Label>
                <Label Text="Item 2"></Label>
                <Label Text="Item 3"></Label>
                <Label Text="Item 4"></Label>
                <Label Text="Item 5"></Label>
            </StackLayout>
        </DataTemplate>
    </customExpanderView:CustomExpander.BodyContentTemplate>
</customExpanderView:CustomExpander>

Get the code

https://github.com/arvindvishwkarma/ExpanderViewInXamarinForms

How to schedule tasks using Hangfire in ASP.NET Core

In this tutorial, we are going to learn how to create, execute and manage tasks in ASP.NET Core using an open source framework called Hangfire.

These are the different types of background jobs supported by Hangfire.

  • Fire-and-forget jobs – are executed only once and almost immediately after creation.
  • Delayed jobs – are executed only once too, but not immediately, after a certain interval of time.
  • Recurring jobs – fire many times on the specified CRON schedule.
  • Continuation jobs – are executed when its parent job has been finished.
  • Batch jobs (Pro) – group of background jobs that is created atomically and considered as a single entity.
  • Batch Continuations (Pro) – fired when all background jobs in a parallel batch finished.

EmailService.cs

using System;
using System.Net;
using System.Net.Mail;
using System.Text;

namespace HangfireDemo.Services
{
    public class EmailService
    {
        private SmtpClient BuildClient()
        {
            var smtpClient = new SmtpClient(AppConsts.SMPT_HOST, AppConsts.SMPT_PORT);
            try
            {
                smtpClient.Credentials = new NetworkCredential(AppConsts.SMTP_USERNAME, AppConsts.SMTP_PASSWORD);
                smtpClient.EnableSsl = true;
            }
            catch (Exception e)
            {
                smtpClient.Dispose();
                throw;
            }
            return smtpClient;
        }

        public void Send(string to, string subject, string body)
        {
            Send(new MailMessage
            {
                To = { to },
                Subject = subject,
                Body = body,
                IsBodyHtml = true
            });
        }

        private void Send(MailMessage mail)
        {
            using (var smtpClient = BuildClient())
            {
                mail.From = new MailAddress(AppConsts.SMTP_USERNAME, AppConsts.EMAIL_DISPLAY_NAME, Encoding.UTF8);
                smtpClient.Send(mail);
            }
        }
    }
}

NotificationService.cs

using HangfireDemo.Models;

namespace HangfireDemo.Services
{
    public class NotificationService
    {
        public void Notify(int messageId)
        {
            using (HangfireDbContext context = new HangfireDbContext())
            {
                var message = context.Messages.Find(messageId);
                if (message != null)
                {
                    EmailService emailService = new EmailService();
                    emailService.Send(message.ToAddress, message.Subject, message.Content);
                    message.IsSent = true;
                    context.SaveChanges();
                }
            }
        }
    }
}

Send email to an user with creating background job using Hangfire.

// Fire-and-forget
BackgroundJob.Enqueue<NotificationService>(m => m.Notify(message.Id));

 

// Delayed
BackgroundJob.Schedule<NotificationService>(m => m.Notify(message.Id), TimeSpan.FromSeconds(30));

 

// Recurring
RecurringJob.AddOrUpdate<NotificationService>("SendNotify-" + message.Id, m => m.Notify(message.Id), Cron.Daily);