IMPORTANT: Post-upgrade manual steps
When upgrading from older than immediately preceding version of Alvao, first perform the post-upgrade steps for all the versions that were skipped in their chronological order.
SQL scripts
The storage of object property values and their inheritance has been changed.
The tblProperty
table no longer exists in the database, nor do the vProperty
and vPropertyInherited
views.
There are following tables available instead:
NodeCust
- storage of own and inherited property values. Table columns have the same type as the property definition.ClassKind
- properties defined for each object type.NodeColumnInheritance
- inheritable (InheritedFromNodeId = NULL) and inherited (InheritedFromNodeId != NULL) properties of objects.
There is also the helpful view vNodeProperty
and stored procedure spNodeProperty
.
You need to update your queries according to the new database scheme.
Example 1
Select hostname (not inherited) of a specific object.
ALVAO 11.2:
select pk.txtValue [Hostname]
from vPropertyKind pk
where pk.lintNodeId = 10 and pk.intKindCode = 3 --HostName
ALVAO 25.1:
select nc.HostName
from vNodeProperty np
join NodeCust nc on nc.NodeId = np.NodeId
where np.NodeId = 10 and np.InheritedFromNodeId is null and np.KindCode = 3 --HostName
Example 2
Select organization name of a specific object. Property can be inherited
ALVAO 11.2:
select pk.txtValue [Organization name]
from vPropertyKindInherited pk
where pk.lintNodeId = 20 and pk.txtKind = N'Organization name'
ALVAO 25.1:
select nc.OrganizationName
from NodeCust nc
where nc.NodeId = 20
Example 3
Select all properties (incl. inherited) with values of a specific object.
ALVAO 11.2:
select pk.txtKind [Property name], pk.txtValue [Property value]
from vPropertyKindInherited pk
where pk.lintNodeId = 30
ALVAO 25.1:
declare @nodes Node
insert into @nodes select 30
declare @props NodeProperty
insert into @props
exec [dbo].[spNodeProperty] @nodes
select k.txtName [Property name], p.TextValue [Property value]
from @props p
join tblKind k on k.intKindId = p.KindId
where p.NodeId = 30
Custom Apps
When upgrading from ALVAO 11.2, you need to modify you existing custom extensions, see ALVAO Asset Management Custom Apps or ALVAO Service Desk Custom Apps. Modify the source files and scripts as described on this page. If you are upgrading from ALVAO 11.1 or earlier, first convert the custom extensions to ALVAO 11.2.
- Alvao.API – Common.Database.ReadColumn – Bit values – Returns "0"/"1" instead of localized "Yes"/"No". We have reverted behavior to its prior state from SD WS. If you want to return a localized value instead of logical value (0/1), use Common.CustomColumn.GetValue and optional parameter returnBitAsNumber set as false. (T155790ALVAO).
- IObjectPropertyAutoAction scripts – Method OnObjectPropertyModifying now returns an ObjectPropertyModifyResult object instead of Tuple. You need to change the definition of this method to public ObjectPropertyModifyResult OnObjectPropertyModifying(ObjectPropertyEventArgs e). Then you need to return an object of this type from described method (ObjectPropertyModifyResult has parameters bool and string, similarly as a Tuple in previous version).
- IObjectPropertyAutoAction scripts - Methods OnObjectPropertyModifying and OnObjectPropertyModified now accept object of type ObjectPropertyEventArgs as a parameter. You need to change the definition of these methods to public ObjectPropertyModifyResult OnObjectPropertyModifying(ObjectPropertyEventArgs e) and public void OnObjectPropertyModified(ObjectPropertyEventArgs e). This object contains all parameters from previous version, so instead of using parameter personId, now you will use e.PersonId.
You should not use String.GetHashCode to identify Custom Apps, because the method is not stable and can return various hash codes in different .NET versions and implementations.
Custom icons
The way of specifying the command icons has been changed. Follow the instructions for the IEntityCommand.Show method - Icon member.
Custom Forms
When upgrading from ALVAO 11.2, you need to modify you existing custom forms, see Custom form for submitting new ticket or Custom ticket approval form. Modify the .cs and .cshtml files as described on this page. If you are upgrading from ALVAO 11.1 or earlier, first convert the custom extensions to ALVAO 11.2.
You need to rewrite at least following parts of code:
- Replace usings Alvao.ServiceDesk.ServiceDeskWebApp... with Alvao.WebApp... in all source files.
ALVAO 11.2:
using Alvao.ServiceDesk.ServiceDeskWebApp.Infrastructure.Custom;
ALVAO 25.1:
using Alvao.WebApp.Infrastructure.Custom;
- Replace using System.Web.Mvc with Microsoft.AspNetCore.Mvc.
ALVAO 11.2:
using System.Web.Mvc;
ALVAO 25.1:
using Microsoft.AspNetCore.Mvc;
- If you are using CustomPageController as a base class for your controller class, add constructor that takes IHttpContextAccessor parameter:
ALVAO 11.2:
public class MyCustomController : CustomPageController
{
...
}
ALVAO 25.1:
using Microsoft.AspNetCore.Http;
...
public class MyCustomController : CustomPageController
{
...
public MyCustomController(IHttpContextAccessor httpContextAccessor)
: base(httpContextAccessor)
{
}
...
}
- Add using to standard resources if you use them and access them only through the Localization class.
ALVAO 11.2:
throw new CustomHttpException(
HttpStatusCode.Forbidden, Resources.Localization.AccessDenied);
ALVAO 25.1:
using Alvao.WebApp.Resources;
...
throw new CustomHttpException(
HttpStatusCode.Forbidden, Localization.AccessDenied);
- Change your namespaces from Alvao.ServiceDesk.ServiceDeskWebApp.Custom... to Alvao.WebApp.Custom... in all your classes.
ALVAO 11.2:
namespace Alvao.ServiceDesk.ServiceDeskWebApp.Custom.MyFormController
ALVAO 25.1:
namespace Alvao.WebApp.Custom.MyFormController
- Remove ControllerContext parameter from constructors and methods in classes inheriting SelectCallbackResponse class.
ALVAO 11.2:
public MyGridSelectResponse(MyGridGrid grid, ControllerContext ctx)
: base(grid, ctx)
ALVAO 25.1:
public MyGridSelectResponse(MyGridGrid grid)
: base(grid)
- Instead of creating a new instance of UrlHelper, call its static methods directly.
ALVAO 11.2:
UrlHelper helper = new UrlHelper(ctx.RequestContext);
Dictionary<string, object> result = new Dictionary<string, object>();
result.Add("link", helper.DefaultAction(
"Index", "Ticket", new { Id = rowData["iHdTicketId"] }));
ALVAO 25.1:
Dictionary<string, object> result = new Dictionary<string, object>();
result.Add("link", UrlHelper.DefaultAction(
"Index", "Ticket", new { Id = rowData["iHdTicketId"] }));
- Change the way you read query parameters.
ALVAO 11.2:
Request.Params["TicketId"]
ALVAO 25.1:
- In controller:
HttpContext.GetParam("TicketId")
- In view:
ViewContext.HttpContext.GetParam("ReturnUrl")
- Get the caller IP address from the connection.
ALVAO 11.2:
IPAddress HostIp = IPAddress.Parse(Request.UserHostAddress);
ALVAO 25.1:
var HostIp = HttpContext.Connection.RemoteIpAddress;
- Change the type of thrown HTTP exceptions.
ALVAO 11.2:
throw new HttpException();
ALVAO 25.1:
throw new CustomHttpException(HttpStatusCode.InternalServerError);
- Change the way you work with session.
ALVAO 11.2:
UserContactsModel ContactDetails =
Session["UserContactDetails"] as UserContactsModel;
ALVAO 25.1:
var userContactDetails =
HttpContext.Session.GetString("UserContactDetails");
UserContactsModel ContactDetails =
string.IsNullOrEmpty(userContactDetails) ?
null :
JsonConvert.DeserializeObject<UserContactsModel>(userContactDetails);
ALVAO 25.2:
Session is removed from this version. You need to use CacheUtil instead.
CacheUtil.UpdateOrCreateItem($"UserContactDetails_{currentPersonId}", contactDetails, 120);
bool isInCache =
CacheUtil.TryGetFromCache($"UserContactDetails_{currentPersonId}", out UserContactsModel contactDetails);
- Access response headers differently.
ALVAO 11.2:
Response.AddHeader("Content-Disposition", ...);
ALVAO 25.1:
Response.Headers.Append("Content-Disposition", ...);
- Use static method StatusCode for returning a certain status from the controller method.
ALVAO 11.2:
return new HttpStatusCodeResult(
System.Net.HttpStatusCode.NoContent);
ALVAO 25.1:
return StatusCode(StatusCodes.Status204NoContent);
- Add layout to .cshtml if not present:
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
- If you use helpers in cshtml files, rewrite them to functions.
ALVAO 11.2:
- Function declaration:
@helper HelperTest(<T> model)
{
<h1>@Model.Text</h1>
}
- Function calling:
@HelperTest(Model)
ALVAO 25.1:
- Function declaration:
@functions
{
public void HelperTest(<T> model)
{
<h1>@Model.Text</h1>
}
}
- Function calling:
@{
HelperTest(Model);
}
- Use UrlHelper static methods to generate URLs.
ALVAO 11.2:
string editTicketUrl =
VirtualPathUtility.ToAbsolute("~/Ticket/Edit/" + Model.TicketId);
ALVAO 25.1:
string editTicketUrl =
UrlHelper.Content("~/Ticket/Edit/" + Model.TicketId);
Useful UrlHelper methods:
public static string Action(string action, string controller)
public static string Action(string action, string controller,
RouteValueDictionary routeValues)
public static string Content(string contentPath)
public static string Content(string contentPath,
RouteValueDictionary routeValues)
- Use WebUtility instead of HttpUtility to encode texts.
ALVAO 11.2:
HttpUtility.UrlEncode(Model.RelatedAccountName)
ALVAO 25.1:
WebUtility.UrlEncode(Model.RelatedAccountName)
To use WebUtility you also need to add the following line at the beginning of the file:
@using System.Net;
- Change the path to system resources.
ALVAO 11.2:
<img src="~/Content/img/favicon.ico" />
ALVAO 25.1:
<img src="~/wwwroot/img/favicon.ico" />