Windows 7 & .NET 4.0 Beta 1

August 23rd, 2009 admin No comments

I upgraded to Windows 7 today and failed to Uninstall .NET 4.0 and VS2010 BETA 1. This left me with non working SQL Management Studio (2005 & 2008) with the error “Microsoft SQL Management Studio Package failed to load”

It also screwed up all my Red Gate software and VS2010. Then I found out you should install Windows 7 after removing .NET 4.0 BETA 1 and Visual Studio other wise you will have to flatten your PC and do a fresh install as the .NET Framework is broken and unfixable. Not really true. I found this worked for me.

Remove .NET 4.0 BETA 1

For x86 OS:

cmd /c "msiexec /x {19BD09BF-3BBD-3663-A5ED-50B6B2B07E42} /qb"
cmd /c "msiexec /x {1DF6A8F6-5048-323F-8758-DA533CE0F07E} /qb"

For x64 OS:

cmd /c "msiexec /x {175D5555-EE49-3033-99AF-BC1E206223FD} /qb"
cmd /c "msiexec /x {13B27C82-19BA-3494-9420-F932B40673CA} /qb"

Then

  • Reboot
  • Uninstall Visual Studio 2010 and its redistributables
  • Reboot
  • Install .NET 4.0
  • Reboot
  • Install Visual 2010

Links to this :-

Download .NET 4.0 Beta 1
MSDN Forums where I found above info.
Hanselman – Before Upgrading To Windows 7

Now I can wait until I get an SSD drive before I do a clean install :-) .

Categories: Uncategorized Tags:

Don’t buy Norton 360

July 1st, 2009 admin 1 comment

I don’t normally rant on this blog, but don’t buy this product it’s rubbish. It slows down you pc to a crawl, takes up loads of resources, crashes trying to backup your data. Last time I ever spend money on Symantec software.

p.s. Can’t even attempt to get a refund.

Update

I have just uninstalled it and quite shocked how much quicker my computer is……

Categories: Uncategorized Tags:

ActionImage – ASP.NET MVC

June 12th, 2009 admin 6 comments

I was in the middle of doing some grid work using the MVC Contrib UI Grid and need an image column. It was a bit messy and a struggle. Turns out there is not a ActionImage helper that behaves like ActionLink. There are plenty of quick hacks about but I wanted some that behaves the same as ActionLink with the same overloads and some extra bits.

It supports all the normal overloads that ActionLink provides in System.Web.Mvc.Html and the generic versions from Microsoft.Web.Mvc.Html. It also support html attributes for both the anchor tag and the image tag.

Also one thing the Generic version of ActionLink does not have is the ability to specify additional route values as well as the action parameters. ActionImage supports the merging of the action parameters and additional route values.

Any suggestions, improvements, fixes, are always welcome.

Regards Tobi.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.Web.Mvc.Internal;
 
namespace GMS.Web.Mvc.Html
{
    public static class HtmlHelpers
    {
 
        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName)
        {
            return htmlHelper.ActionImage(imageUrl, linkText, actionName, null, new RouteValueDictionary(), new RouteValueDictionary());
        }
 
        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, object routeValues)
        {
            return htmlHelper.ActionImage(imageUrl, linkText, actionName, null, new RouteValueDictionary(routeValues), new RouteValueDictionary());
        }
 
        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, string controllerName)
        {
            return htmlHelper.ActionImage(imageUrl, linkText, actionName, controllerName, new RouteValueDictionary(), new RouteValueDictionary());
        }
 
        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, RouteValueDictionary routeValues)
        {
            return htmlHelper.ActionImage(imageUrl, linkText, actionName, null, routeValues, new RouteValueDictionary());
        }
 
        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, object routeValues, object htmlanchorAttributes)
        {
            return htmlHelper.ActionImage(imageUrl, linkText, actionName, null, new RouteValueDictionary(routeValues), new RouteValueDictionary(htmlanchorAttributes), null);
        }
 
        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, RouteValueDictionary routeValues, IDictionary<string, object> htmlanchorAttributes, IDictionary<string, object> htmlImageAttributes)
        {
            return htmlHelper.ActionImage(imageUrl, linkText, actionName, null, routeValues, htmlanchorAttributes, htmlImageAttributes);
        }
 
        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, string controllerName, object routeValues, object htmlanchorAttributes)
        {
            return htmlHelper.ActionImage(imageUrl, linkText, actionName, controllerName, new RouteValueDictionary(routeValues), new RouteValueDictionary(htmlanchorAttributes), null);
        }
 
        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, object routeValues, object htmlanchorAttributes, object htmlImageAttributes)
        {
            return htmlHelper.ActionImage(imageUrl, linkText, actionName, controllerName, protocol, hostName, fragment, new RouteValueDictionary(routeValues), new RouteValueDictionary(htmlanchorAttributes), new RouteValueDictionary(htmlImageAttributes));
        }
 
        public static string ActionImage<TController>(this HtmlHelper htmlHelper, Expression<Action<TController>> action, string imageUrl, string linkText) where TController : Controller
        {
            return htmlHelper.ActionImage(action, imageUrl, linkText, null, null, null);
        }
 
        public static string ActionImage<TController>(this HtmlHelper htmlHelper, Expression<Action<TController>> action, string imageUrl, string linkText, object routeValues) where TController : Controller
        {
            return htmlHelper.ActionImage(action, imageUrl, linkText, routeValues, null, null);
        }
 
        public static string ActionImage<TController>(this HtmlHelper htmlHelper, Expression<Action<TController>> action, string imageUrl, string linkText, object routeValues, object htmlanchorAttributes, object htmlImageAttributes) where TController : Controller
        {
            return htmlHelper.ActionImage(action, imageUrl, linkText, routeValues, new RouteValueDictionary(htmlanchorAttributes), new RouteValueDictionary(htmlImageAttributes));
        }
 
        public static string ActionImage<TController>(this HtmlHelper htmlHelper, Expression<Action<TController>> action, string imageUrl, string linkText, object routeValues, IDictionary<string, object> htmlanchorAttributes, IDictionary<string, object> htmlImageAttributes) where TController : Controller
        {
 
            var _routeValuesFromExpression = ExpressionHelper.GetRouteValuesFromExpression(action);
            var _mergedRouteValues = MergeRouteValueDictionaries(_routeValuesFromExpression, new RouteValueDictionary(routeValues));
 
            // get the action name
            //
            var _actionName = ((MethodCallExpression)action.Body).Method.Name;
 
            // get the bare url for the Action using the current
            // request context
            //     
            var _url = new UrlHelper(htmlHelper.ViewContext.RequestContext).Action(_actionName, _mergedRouteValues);
 
            return GetImageLink(_url, linkText, imageUrl, htmlanchorAttributes, htmlImageAttributes);
 
        }
 
        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlanchorAttributes, IDictionary<string, object> htmlImageAttributes)
        {
            // get the bare url for the Action using the current
            // request context
            //
            var _url = new UrlHelper(htmlHelper.ViewContext.RequestContext).Action(actionName, controllerName, routeValues);
 
            return GetImageLink(_url, linkText, imageUrl, htmlanchorAttributes, htmlImageAttributes);
 
        }
 
        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary<string, object> htmlanchorAttributes, IDictionary<string, object> htmlImageAttributes)
        {
 
            // get the bare url for the Action using the current
            // request context
            //
            var _url = new UrlHelper(htmlHelper.ViewContext.RequestContext).Action(actionName, controllerName, routeValues, protocol, hostName);
 
            return GetImageLink(_url, linkText, imageUrl, htmlanchorAttributes, htmlImageAttributes);
 
        }
 
        /// <summary>
        /// Build up the anchor and image tag.
        /// </summary>
        /// <param name="url">The URL.</param>
        /// <param name="linkText">The link text.</param>
        /// <param name="imageUrl">The image URL.</param>
        /// <param name="htmlanchorAttributes">The HTML anchor attributes.</param>
        /// <param name="htmlImageAttributes">The HTML image attributes.</param>
        /// <returns></returns>
        internal static string GetImageLink(string url, string linkText, string imageUrl, IDictionary<string, object> htmlanchorAttributes, IDictionary<string, object> htmlImageAttributes)
        {
            // build up the image link.
            // <a href=\"ActionUrl\"><img src=\"ImageUrl\" alt=\"Your Link Text\" /></a>
            //
 
            var _linkText = !string.IsNullOrEmpty(linkText) ? HttpUtility.HtmlEncode(linkText) : string.Empty;
 
            // build the img tag
            //
            TagBuilder _image = new TagBuilder("img");
            _image.MergeAttributes(htmlImageAttributes);
            _image.MergeAttribute("src", imageUrl);
            _image.MergeAttribute("alt", _linkText);
 
            // build the anchor tag
            //
            TagBuilder _link = new TagBuilder("a");
            _link.MergeAttributes(htmlanchorAttributes);
            _link.MergeAttribute("href", url);
 
            // place the img tag inside the anchor tag.
            //
            _link.InnerHtml = _image.ToString(TagRenderMode.Normal);
 
            // render the image link.
            //
            return _link.ToString(TagRenderMode.Normal);
 
        }
 
 
        /// <summary>
        /// Merges the 2 source route value dictionaries.
        /// </summary>
        /// <param name="routeValueDictionary1">RouteValueDictionary 1.</param>
        /// <param name="routeValueDictionary2">RouteValueDictionary 2.</param>
        /// <returns></returns>
        internal static RouteValueDictionary MergeRouteValueDictionaries(RouteValueDictionary routeValueDictionary1, RouteValueDictionary routeValueDictionary2)
        {
            var _mergedRouteValues = new RouteValueDictionary();
 
            if ((routeValueDictionary1 != null) & (routeValueDictionary2 != null))
            {
                foreach (KeyValuePair<string, object> routeElement in routeValueDictionary1)
                {
                    _mergedRouteValues[routeElement.Key] = routeElement.Value;
                }
 
                foreach (KeyValuePair<string, object> routeElement in routeValueDictionary2)
                {
                    _mergedRouteValues[routeElement.Key] = routeElement.Value;
                }
 
                return _mergedRouteValues;
            }
 
            return null;
        }
 
    }
 
}

Kill all database connections

June 7th, 2009 admin No comments

Just came across this script – very useful

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
--------------------------------------------------------------------------------------
/*** CREATED BY AJITH DHARWAR                                                     ***/
/*** This procedure will accept a DB name and drop all connections to the DB.    ***/
--------------------------------------------------------------------------------------
CREATE PROCEDURE usp_killDBConnections
    @DBName VARCHAR(50),
    @withmsg BIT = 1
AS 
    SET NOCOUNT ON
    DECLARE @spidstr VARCHAR(8000)
    DECLARE @ConnKilled SMALLINT
    SET @ConnKilled = 0
    SET @spidstr = ''
 
    IF DB_ID(@DBName) > 4 
        BEGIN
            PRINT 'Connections to system databases cannot be killed'
            RETURN
        END
 
    SELECT  @spidstr = COALESCE(@spidstr, ',') + 'kill ' + CONVERT(VARCHAR, spid) + '; '
    FROM    master..sysprocesses
    WHERE   dbid = DB_ID(@DBName)
 
    IF LEN(@spidstr) &gt; 0 
        BEGIN
            EXEC ( @spidstr
                )
 
            SELECT  @ConnKilled = COUNT(1)
            FROM    master..sysprocesses
            WHERE   dbid = DB_ID(@DBName) 
 
        END
 
    IF @withmsg = 1 
        PRINT CONVERT(VARCHAR(10), @ConnKilled) + ' Connection(s) killed for DB ' + @DBName
GO

You can then use it like this

1
EXEC sp_msforeachdb 'EXEC usp_killDBConnections @DBName=''?'''

Or like this

1
EXEC usp_killDBConnections @DBName='MyDatabase'
Categories: Programming, SQL Tags: ,

SQL Report Server & ASP.MVC

June 7th, 2009 admin 5 comments

I have used MS SQL Report server a lot and one of the most common scenarios is to render a report and have it download a PDF / Excel etc. I have not seen many posts regarding how to do this end-to-end using MVC. So I thought I share my method.

The demo project will be split into 3 parts.

  1. The Report Server Execution Service.
    2. The Report Server Repository Layer.
    3. The Report Server Service Layer.
    4. The User Interface.
    You’ll need
  1. Visual Studio 2008
  2. ASP.MVC RTM
  3. SQL Server 2005/2008

You’ll also have installed and working the MSSQL Report Server and a test report.Create a New Blank Solution SQL Server Report Solution

imageAnd then add 2 Class Libraries and a MVC Web Site – You can choose whether or not to add the MVC Test projects.

  • Demos.SqlReports.Data
  • Demos.SqlReports.Services
  • Demos.SqlReports.Web

I’ll also add a test project for the Data and Service Layer, I’m just using the default unit test framework that comes with VS 2008. You can of course use something else (nUnit, xUnit etc).

  • Demos.SqlReports.Tests
    You should have something like this now.

image 

We need to add a Web Reference to the Report Server at the data layer. My Report Server Execution Service URL is

http://localhost/ReportServer$SQLSERVER_001/ReportExecution2005.asmx

Yours may differ so check it in IIS.

Also, I’m adding a web reference – not a service reference. You can do this though the add service reference dialog box by clicking Advanced | Add Web Reference.

image

I always postfix Proxy on the end of the Web Reference Name for clarity.

Once added rename Class 1  to ReportServerRepository.cs and also create an Interface Class IReportsRepository.cs

Move these files into a sub folder Data so they are organised.

image

Let’s add some code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
using System;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;
using System.Web.Services.Protocols;
using Demos.SqlReports.Data.ReportExecution2005Proxy;
 
namespace Demos.SqlReports.Data
{
 
    ///
    /// Contains the response data from a RenderReport request
    /// to the report server.
    ///
    public sealed class RenderReportResponse
    {
        public byte[] ReportData { get; set; }
        public ExecutionInfo ExecutionInfo { get; set; }
        public ReportExecution2005Proxy.Warning[] Warnings { get; set; }
        public string SessionId { get; set; }
        public string ContentType { get; set; }
        public string HistoryID { get; set; }
        public string DevInfo { get; set; }
        public string Encoding { get; set; }
        public string MimeType { get; set; }
        public string Extension { get; set; }
        public string[] StreamIds { get; set; }
    }
 
    ///
    /// Report Server Repository
    ///
    public sealed class ReportServerRepository : IReportsRepository
    {
 
        #region Constructors
 
        ///
        /// Initializes a new instance of the  class.
        ///
        public ReportServerRepository()
        {
            this.Initialise();
        }
 
        #endregion
 
        #region Declarations
 
        private NetworkCredential netCredential;
        private ReportExecutionService webServiceProxy;
 
        #endregion
 
        #region Private Members
 
        ///
        /// Initialises this instance and set the credentials for
        /// the report server.
        ///
        private void Initialise()
        {
 
            webServiceProxy = new ReportExecutionService();
            netCredential = new NetworkCredential("MyUserName", "MyPassword");
            Uri uri = new Uri(webServiceProxy.Url);
            ICredentials credentials = netCredential.GetCredential(uri, "Basic");
            webServiceProxy.Credentials = credentials;
            webServiceProxy.PreAuthenticate = true;
 
        }
 
        ///
        /// Gets the type of the content.
        ///
        ///
The file extension.
        ///
        private static string GetContentType(string fileExtension)
        {
            switch (fileExtension.ToLower())
            {
                case ".pdf": return "application/pdf";
                case ".tif": return "image/tiff";
                case ".xls": return "application/ms-excel";
                case ".xml": return "text/xml";
                default: return "text/plain";
            }
 
        }
 
        ///
        /// Renders the report.
        ///
        ///
The parameters.
        ///
The report path.
        ///
The format.
        ///
        private static RenderReportResponse RenderReport(ReportExecution2005Proxy.ParameterValue[] parameters, string reportPath, string format)
        {
 
            using (var rs = new ReportExecutionService())
            {
 
                try
                {
 
                    rs.Credentials = CredentialCache.DefaultCredentials;
 
                    // Render arguments
                    //
                    const string _historyID = null;
                    const string _devInfo = @"False";
                    string _encoding;
                    string _mimeType;
                    string _extension;
                    ReportExecution2005Proxy.Warning[] _warnings;
                    string[] _streamIDs;
 
                    ExecutionInfo _execInfo = new ExecutionInfo();
                    ExecutionHeader execHeader = new ExecutionHeader();
 
                    rs.ExecutionHeaderValue = execHeader;
                    _execInfo = rs.LoadReport(reportPath, _historyID);
 
                    rs.SetExecutionParameters(parameters, "en-us");
                    String SessionId = rs.ExecutionHeaderValue.ExecutionID;
 
                    var _reportData = rs.Render(format, _devInfo, out _extension, out _encoding, out _mimeType, out _warnings, out _streamIDs);
 
                    var _response = new RenderReportResponse
                                        {
                                            ReportData = _reportData,
                                            ExecutionInfo = _execInfo,
                                            Warnings = _warnings,
                                            SessionId = SessionId,
                                            ContentType = GetContentType(format),
                                            HistoryID = _historyID,
                                            DevInfo = _devInfo,
                                            Encoding = _encoding,
                                            MimeType = _mimeType,
                                            Extension = _extension,
                                            StreamIds = _streamIDs
                                        };
                    return _response;
 
                }
                catch (SoapException e)
                {
 
                    // handle exception
                    //
                    throw new ApplicationException(
                        string.Format("Error occurred rendering the report : {0}", reportPath), e);
 
                }
 
            }
 
        }
 
        #endregion
 
        #region IReportServerRepository Members
 
        ///
        /// Renders the Demo Report.
        ///
        ///
The reportParameter.
        ///
        public RenderReportResponse RenderDemoReport(string reportParameter)
        {
 
            var _params = new[] { new ReportExecution2005Proxy.ParameterValue { Name = "p_ReportParameter", Value = reportParameter } };
 
            return RenderReport(_params, "My Demo Report", "PDF");
        }
 
        #endregion
 
    }
 
}

And add some to the interface class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace Demos.SqlReports.Data
{
    interface IReportsRepository
    {
 
        ///
        /// Renders the Demo Report.
        ///
        ///
The reportParameter.
        ///
        RenderReportResponse RenderDemoReport(string reportParameter);
 
    }
}

The reason for returning a class of RenderReportResponse back is that we can have the whole response delivered to the UI and make use of it if required.

Ok let’s add some code to the service class.

Rename Class 1  to ReportService.cs and also create an Interface Class IReportService.cs

The purpose of the interfaces and the service class is to abstract away the implementation of the repository and to decouple as much as possible.

The UI should only ever call the service class. You can then swap out repositories easily when testing code or using an alternative repository. It also lends its self well to a plug-in architecture or if you plan to implement IoC / Dependency Injection later on.

Code for the Service Class

(make sure you have added a project reference for Demos.SqlReports.Data)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Demos.SqlReports.Data;
 
namespace Demos.SqlReports.Services
{
    public partial class ReportService : IReportService
    {
 
        readonly IReportsRepository _repository;
 
        ///
        /// Creates a ReportService based on the passed-in repository
        ///
        ///
An IReportsRepository
        public ReportService(IReportsRepository repository)
        {
            _repository = repository;
 
            if (_repository == null)
                throw new InvalidOperationException("Repository cannot be null");
 
        }
 
        ///
        /// Creates a ReportService based on the default repository
        ///
        public ReportService()
        {
            _repository = new ReportServerRepository();
        }
 
        #region IReportService Members
 
        public RenderReportResponse RenderDemoReport(string reportParameter)
        {
            return _repository.RenderDemoReport(reportParameter);
        }
 
        #endregion
    }
}

 

Code for the Service Interface Class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Demos.SqlReports.Data;
 
namespace Demos.SqlReports.Services
{
    public interface IReportService
    {
 
        ///
        /// Renders the Demo Report.
        ///
        ///
The reportParameter.
        ///
        RenderReportResponse RenderDemoReport(string reportParameter);
 
    }
 
}

 

Move these files into a sub directory i.e. Reports. Build the project make sure there are no errors.

 

Implementing the UI

 

In the MVC Project we are going to use the default HomeController for our demo. Add a project reference for the Data and Service Layers.

The first thing we need to do is create a class for the ActionResultHelper.cs. Add the class file in a subdirectory Helpers (keep the class namespace flat i.e. Demos.SqlReports.Web remove any namespace additions if you create the sub directory first.

Add the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Demos.SqlReports.Services;
using Demos.SqlReports.Data;
 
namespace Demos.SqlReports.Web
{
    public class ReportServerResult : ActionResult
    {
        public RenderReportResponse ReportData { get; set; }
        public string FileName { get; set; }
 
        public override void ExecuteResult(ControllerContext context)
        {
 
            context.HttpContext.Response.Clear();
            context.HttpContext.Response.ClearHeaders();
            context.HttpContext.Response.ContentType = ReportData.ContentType;
            context.HttpContext.Response.AddHeader("content-disposition", "attachment; filename="" + FileName + """);
            context.HttpContext.Response.BinaryWrite(ReportData.ReportData);
            context.HttpContext.Response.Flush();
 
        }
    }
}

Let me explain a little what’s going on here. By inheriting the ActionResult base class we can pass the report servers response directly to the response stream of the Controller Action. This is a neat way because it also allows you to Unit Test the response and you can reuse it anywhere you render a report.

Let’s create an Action in Home Controller.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Demos.SqlReports.Services;
using Demos.SqlReports.Data;
 
namespace Demos.SqlReports.Web.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {
 
        private readonly IReportService _reportService;
 
        public HomeController()
        {
            _reportService = new ReportService(new ReportServerRepository());
        }
 
        public ActionResult Index()
        {
            ViewData["Message"] = "Welcome to ASP.NET MVC!";
 
            return View();
        }
 
        public ActionResult About()
        {
            return View();
        }
 
        ///
        /// Gets the demo report.
        ///
        ///
The report parameter.
        ///
        public ActionResult GetDemoReport(string reportparameter)
        {
            // call the report service and render the report
            //
 
            var _response = _reportService.RenderDemoReport(reportparameter);
 
            // returnn the result using a custom action result class.
            //
            return new ReportServerResult { FileName = "Demo Report.pdf", ReportData = _response };
 
        }
 
    }
}

As you can see the code is nice and concise. The Response Data from service layer is passed straight into the ReportServerResult  which outputs the report to the response stream.

Add an ActionLink to the Index.aspx file

1
2
3
4
5
6
7
8
9
&lt; %@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %&gt;
 
    Home Page
<h2>
        &lt; %= Html.Encode(ViewData["Message"]) %&gt;</h2>
To learn more about ASP.NET MVC visit <a title="ASP.NET MVC Website" href="http://asp.net/mvc">
            http://asp.net/mvc</a>.
 
        &lt; %= Html.ActionLink("Render Report","GetDemoReport", "HomeController",new{ reportparameter = "ParameterValue"}) %&gt;

 

That’s it. normally I’d build the unit tests before jumping into the code but this isn’t a session on TDD. I’ll leave that bit to you. Next I’d like to get the Report Viewer control working with ASP.MVC. You can download the test solution here.

Download Solution – SQL Server Report Solution.zip

MVC – Strongly Typed Global ViewData

June 2nd, 2009 admin 2 comments

Most MVC stuff I have been doing has been quite basic and the knowledge gleaned off many blog sites ( thanks to you all :-) )I’m not a prolific blogger – too busy!!!, I’ll only blog when I have something to useful to share that isn’t easy to find.

I was looking for a way to provide ViewData at the Model level so that I could have some parameters available after every action that were strongly typed and injected into the ActionResult instead of ViewData["MyData"]. I want to use Model.MyData

I had a good search about but nothing definitive so I cam up with this.

The Base Controller Class.

It’s always a good idea to have you own base controller that is inherited from your other controllers. Here we are using it for storing Global Settings/Properties or any helper methods etc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
using System;
using System.Web.Mvc;
 
namespace GlobalViewData.Controllers
{
 
    /// <summary>
    /// Base data container for ViewData Models
    /// </summary>
    public abstract class BaseFormViewModel
    {
        public string MyData { get; set; }
    }
 
    /// <summary>
    /// Base controller that all controllers inherit from.
    /// </summary>
    public abstract class BaseController : Controller
    {
 
        /// <summary>
        /// Initializes a new instance of the <see cref="BaseController" /> class.
        /// </summary>
        protected BaseController()
        {
            MyData = "I have set this in the BaseController";
        }
 
        public string MyData { get; set; }
 
        /// <summary>
        /// Method called after the action method is invoked.
        /// </summary>
        /// <param name="filterContext" />Contains information about the current request and action.
        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            // check there is data in the Model
            //
            if (filterContext.Controller.ViewData.Model != null)
            {
                // bit of reflection magic and get the types
                //
                Type _baseFormViewModelType = typeof(BaseFormViewModel);
                Type _modelType = filterContext.Controller.ViewData.Model.GetType();
 
                // if the model type is derived from the base type then
                // we can set some properties.
                //
 
                if (_baseFormViewModelType.IsAssignableFrom(_modelType))
                {
                    // inject the value to the ViewData.Model property
                    //
                    _modelType.GetProperty("MyData").SetValue(filterContext.Controller.ViewData.Model, MyData, null);
                }
            }
 
            base.OnActionExecuted(filterContext);
 
        }       
    }
}

The Home Controller Class

This inherits from the BaseController and also has a Data Class called HomeFormViewModel which inherits from BaseFormViewModel.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
 
namespace GlobalViewData.Controllers
{
 
    public class HomeFormViewModel : BaseFormViewModel
    {
        public string LocalData { get; set; }
    }
 
    [HandleError]
    public class HomeController : BaseController
    {
        public ActionResult Index()
        {
            ViewData[&quot;Message&quot;] = "Welcome to ASP.NET MVC!";
 
            return View();
        }
 
        public ActionResult About()
        {
            var _formData = new HomeFormViewModel {LocalData = "I have set this in the Home Controller"};
 
            return View(_formData);
        }
    }
}

 

When the About Action is called the  HomeFormViewModel  is populated and then caught by the BaseController OnActionExecuted method which injects the required data into the HomeFormViewModel which is derived from BaseFormViewModel

In About.aspx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
< %@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<HomeFormViewModel>" %>
 
< %@ Import Namespace="GlobalViewData.Controllers" %>
<asp :Content ID="aboutTitle" ContentPlaceHolderID="TitleContent" runat="server">
    About Us
</asp>
<asp :Content ID="aboutContent" ContentPlaceHolderID="MainContent" runat="server">
    <h2>
        About</h2>
    <p>
        Global - From BaseController
        < %=Html.Encode(Model.MyData) %>
    </p>
    <p>
        Local - From HomeController
        < %=Html.Encode(Model.LocalData) %>
    </p>
</asp>

As you can see from the image below the data is populated.

image

Hope this is useful!

Adventures in MVC.NET

February 10th, 2009 admin No comments

I have been watching the progress of the new MVC framework for Micrsoft.NET and must say I can’t wait to start using it. However like all things new I have been waiting for some proper guidance and for the software to get to release status – which should not be far off (a month or so). Scott Guthrie has been making some excellent post regarding the progress and features of MVC – http://weblogs.asp.net/scottgu/archive/tags/MVC/default.aspx

I have also being following Rob Conerly series on MVC Storefront http://blog.wekeroad.com/mvc-storefront which is providing some excellent learing both in TDD and DDD practices apart from the MVC framework, I suggest anyone looking at .NET development with or without the MVC part check out and watch the series, you’ll learn at lot. The series up to EP 23 is published here - http://www.asp.net/learn/mvc-videos the rest can be found on Rob’s blog.

I have a real work app to write and I’d like to use MVC so when I start using it I’ll blog a bit more about it.

Regards

Tobi.

Categories: Software Tags: ,

PowerDNS on SuSE Linux & SQL Server 2005 – Part 1

October 19th, 2008 golum1900 11 comments

I have been working on a scenario for one of our services and that’s our DNS back-end. It has to achieve the following criteria.

  • A Fast and Reliable DNS Service
  • SQL Server Database Back-end for management. (as we already run MS SQL as standard)
  • Linux Based DNS Server (better supported, free & reliable)
  • VMware Virtual Server

So after a good look around we have decided on PowerDNS, SuSE Linux Enterprise 10.1 & MS SQL Server 2005 as the DBMS.

Now this is where the fun starts. I’m no Linux expert but I can find my way around pretty well. Let me tell you, getting this to work was not easy, 3 long days of head scratching, disparate documentation and perseverance. This is probably the only HOWTO there is on doing this.

Assumptions.

  1. You already have SQL 2005 Installed and available on the network. 
  2. Your relativity competent in Windows / Linux administration. 
  3. You understand DNS concepts.

Steps to install SuSE on VMware Workstation

  1. Create your virtual machine environment and start it up. In my case I have chosen VMware Workstation 5 with ESX Server 3 compatibility. 512MB of RAM and 4GB of disk space split into 2GB files.
  2. Install SuSE Linux by mounting the ISO image on the virtual machines CDROM drive. I have chosen just to install the base server system but included the C++ compilation tools for building software.
  3. Once SuSE is installed you need to install the VMware tools. Select this from the VM menu. Once installed run the command # /usr/bin/vmware-config-tools.pl this sets up the proper screen drivers and allows things like shared folders, copy & paste between virtual machine and the host.

Hit ctrl-backspace to restart the X windows system. You should now have a base Linux System running under VMware.

First let’s get all the files we need :-

PowerDNS v2.9.22 (Authoritative Name Server)
http://download.opensuse.org/repositories/server:/dns/openSUSE_10.3/i586/pdns-2.9.22-1.1.i586.rpm

PowerDNS v2.9.x OpenDBX Backend (PDNS Database access via OpenDBX)
http://download.opensuse.org/repositories/server:/dns/openSUSE_10.3/i586/pdns-snapshot-backend-opendbx-2.9.x.r1107-3.3.i586.rpm

OpenDBX Library (DBMS API)
http://linuxnetworks.de/opendbx/download/opendbx-1.2.3.tar.gz

FreeTDS Library (allows communication from Linux to various DBMS including SQL Server
ftp://ftp.ibiblio.org/pub/Linux/ALPHA/freetds/stable/freetds-stable.tgz

MySQL header libraries as it is a dependency for PDNS.
http://download.opensuse.org/repositories/server:/database/openSUSE_10.3/i586/libmysqlclient15-5.0.67-20.1.i586.rpm

Create a suitable directory on you Linux OS and copy the downloaded files to this directory. I have used /root/Documents/PDNS. The shared folders directory on the Linux guest is under /mnt/hgfs.

Once you have the files extract the tar’s for OpenDBX & FreeTDS.

Installing FreeTDS and Connecting to MS SQL Server

The first item we need to install is FreeTDS, basically TDS stands for Tabular Data Stream and is the protocol that MS SQL Server uses to communicate with it’s clients. You can read more about it @ http://www.freetds.org/

Open a terminal window up, change directory to where you extracted the FreeTDS software to.

Run the following commands to build and install it:-

$ ./configure
$ make
$ make install

Great, if you didn’t get any errors we can now configure the connection. Load up gedit and open /usr/local/etc/freetds.conf go the end of the file and add the following:-

# My connection to SQL Server 2005 on PC12SQL2005D_1
[MySQLServer2005]
 host = pc21.outerin.uk-net
 instance = SQL2005D_1
; port = 1433
 tds version = 8.0

Subsitute the host, instance or port for that of your SQL Server Instance. If you use instance then the port is auto-detected. Save the file and quit.

NOTE : Make sue you can resolve the remote SQL server and you can get a response. If you can’t make sure

a) etc/hosts file has an entry
b) your DNS server is correct.
c) any firewalls allow the SQL traffic through.

Lets test the connection by running the command tsql.

 

Excellent we now have a connection to SQL Server.

Set up the PowerDNS Database on MS SQL Server.

Execute this script on SQL Server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
USE [master]
 
GO
 
/****** Object:  Database [PowerDNS]    Script Date: 10/17/2008 12:15:22 ******/
 
CREATE DATABASE [PowerDNS] ON PRIMARY
( NAME = N'PowerDNS_Data', FILENAME = N'C:Program FilesMicrosoft SQL ServerMSSQL.1MSSQLDATAPowerDNS_Data.mdf' , SIZE = 3072KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
    LOG ON
( NAME = N'PowerDNS_Log', FILENAME = N'C:Program FilesMicrosoft SQL ServerMSSQL.1MSSQLDATAPowerDNS_Log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
GO
EXEC dbo.SP_DBCMPTLEVEL @dbname = N'PowerDNS', @new_cmptlevel = 90
GO
IF ( 1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled') )
    BEGIN
        EXEC [PowerDNS].[dbo].[SP_FULLTEXT_DATABASE] @ACTION = 'disable'
    END
GO
ALTER DATABASE [PowerDNS] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [PowerDNS] SET ANSI_NULLS OFF
GO
ALTER DATABASE [PowerDNS] SET ANSI_PADDING OFF
GO
ALTER DATABASE [PowerDNS] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE [PowerDNS] SET ARITHABORT OFF
GO
ALTER DATABASE [PowerDNS] SET AUTO_CLOSE OFF
GO
ALTER DATABASE [PowerDNS] SET AUTO_CREATE_STATISTICS ON
GO
ALTER DATABASE [PowerDNS] SET AUTO_SHRINK OFF
GO
ALTER DATABASE [PowerDNS] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE [PowerDNS] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE [PowerDNS] SET CURSOR_DEFAULT GLOBAL
GO
ALTER DATABASE [PowerDNS] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE [PowerDNS] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE [PowerDNS] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE [PowerDNS] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE [PowerDNS] SET ENABLE_BROKER
GO
ALTER DATABASE [PowerDNS] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE [PowerDNS] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE [PowerDNS] SET TRUSTWORTHY OFF
GO
ALTER DATABASE [PowerDNS] SET ALLOW_SNAPSHOT_ISOLATION OFF
GO
ALTER DATABASE [PowerDNS] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE [PowerDNS] SET READ_WRITE
GO
ALTER DATABASE [PowerDNS] SET RECOVERY FULL
GO
ALTER DATABASE [PowerDNS] SET MULTI_USER
GO
ALTER DATABASE [PowerDNS] SET PAGE_VERIFY CHECKSUM
GO
ALTER DATABASE [PowerDNS] SET DB_CHAINING OFF
GO
 
USE [PowerDNS]
GO
/****** Object:  Table [dbo].[domains]    Script Date: 10/17/2008 12:21:59 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[domains]
    (
      [id] [INT] IDENTITY(1, 1)
                 NOT NULL,
      [name] [VARCHAR](255) NOT NULL,
      [type] [VARCHAR](6) NOT NULL,
      [master] [VARCHAR](40) NOT NULL
                             DEFAULT ( '' ),
      [account] [VARCHAR](40) NOT NULL
                              DEFAULT ( '' ),
      [notified_serial] [INT] NULL,
      [last_check] [INT] NULL,
      [status] [CHAR](1) NOT NULL
                         DEFAULT ( 'A' ),
      CONSTRAINT [pk_domains_id] PRIMARY KEY CLUSTERED ( [id] ASC )
        WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
               IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
               ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY],
      CONSTRAINT [unq_domains_name] UNIQUE NONCLUSTERED ( [name] ASC )
        WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
               IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
               ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY]
    )
ON  [PRIMARY]
 
GO
SET ANSI_PADDING OFF
GO
/****** Object:  Table [dbo].[records]    Script Date: 10/17/2008 12:21:59 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[records]
    (
      [id] [INT] IDENTITY(1, 1)
                 NOT NULL,
      [domain_id] [INT] NOT NULL,
      [name] [VARCHAR](255) NOT NULL,
      [type] [VARCHAR](6) NOT NULL,
      [ttl] [INT] NULL,
      [prio] [INT] NULL,
      [content] [VARCHAR](255) NOT NULL,
      [change_date] [INT] NULL,
      CONSTRAINT [pk_records_id] PRIMARY KEY CLUSTERED ( [id] ASC )
        WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
               IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
               ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY]
    )
ON  [PRIMARY]
 
GO
SET ANSI_PADDING OFF
GO
/****** Object:  Table [dbo].[supermasters]    Script Date: 10/17/2008 12:21:59 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[supermasters]
    (
      [ip] [VARCHAR](40) NOT NULL,
      [nameserver] [VARCHAR](255) NOT NULL,
      [account] [VARCHAR](40) NOT NULL
                              DEFAULT ( '' )
    )
ON  [PRIMARY]
 
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[records]
        WITH CHECK
ADD CONSTRAINT [fk_records_domainid] FOREIGN KEY ( [domain_id] ) REFERENCES [dbo].[domains] ( [id] ) ON UPDATE CASCADE
        ON DELETE CASCADE
GO
ALTER TABLE [dbo].[records]
        CHECK CONSTRAINT [fk_records_domainid]
 
USE [master]
GO
CREATE LOGIN [powerdns] WITH PASSWORD= N'secret', DEFAULT_DATABASE= [PowerDNS], DEFAULT_LANGUAGE= [us_english], CHECK_EXPIRATION=
    OFF, CHECK_POLICY= OFF
GO
ALTER LOGIN [powerdns] ENABLE
GO
USE [PowerDNS]
GO
CREATE  USER [powerdns] FOR LOGIN [powerdns]
GO
GRANT DELETE ON [dbo].[domains] TO [powerdns]
GO
GRANT INSERT ON [dbo].[domains] TO [powerdns]
GO
GRANT REFERENCES ON [dbo].[domains] TO [powerdns]
GO
GRANT SELECT ON [dbo].[domains] TO [powerdns]
GO
GRANT UPDATE ON [dbo].[domains] TO [powerdns]
GO
GRANT DELETE ON [dbo].[records] TO [powerdns]
GO
GRANT INSERT ON [dbo].[records] TO [powerdns]
GO
GRANT REFERENCES ON [dbo].[records] TO [powerdns]
GO
GRANT SELECT ON [dbo].[records] TO [powerdns]
GO
GRANT UPDATE ON [dbo].[records] TO [powerdns]
GO
GRANT SELECT ON [dbo].[supermasters] TO [powerdns]
GO

Build and Install the OpenDBX Library

We need to build the OpenDBX library backend for SQL Server 2005 (for other backends please refer to http://www.linuxnetworks.de/doc/index.php/OpenDBX for more info)

Change to the OpenDBX directory where you extracted the files and issue the command

$ ./configure –with-backends=”mssql”
$ make
$ make install

Once completed we need to install PowerDNS and the PowerDNS OpenDBX backend.

Install the MySQL header libraries as it is a dependency for PDNS.

Hit Install to install the package

Install the pdns-2.9.21-17.4.i586.rpm package

Hit Install to install the package.

Install the OpenDBX backend

This package will not install. Instead open it in “File Roller” and extract the contents to /usr/lib/pdns this is where they are looked for.

Testing the PowerDNS installation

Once installed test the PowerDNS installation by issuing the command:-

$ /etc/init.d/pdns monitor

you should see an error message as below.


This means we have successfully installed the PowerDNS server and we now need to configure it. Open the file /etc/pdns/pdns.conf in gedit

Find the following section

#################################
# launch Which backends to launch and order to query them in
#
# launch=

and change to:-

#################################
# launch Which backends to launch and order to query them in
#

launch=opendbx
opendbx-backend=mssql
opendbx-host-read=MySQLServer2005
opendbx-host-write=MySQLServer2005
opendbx-database=PowerDNS
opendbx-username=powerdns
opendbx-password=secret
opendbx-sql-transactbegin=BEGIN TRANSACTION

NOTE: make sure there are no spaces next to the = sign. It won’t work 

Try the command again:-

$ /etc/init.d/pdns monitor

Success we have a Database driven DNS system!!

Testing the DNS

Enter the command

$ host www.example.com 127.0.0.1

The address will not be resolved as we haven’t any data in the database yet. Run the following SQL on the database (you can change the IP addresses and names to suit you own).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
USE
[PowerDNS]
GO
INSERT
INTO domains (name, type) VALUES ('example.com', 'NATIVE');
INSERT
INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'example.com','localhost postmaster@example.com 1','SOA',86400,NULL);
INSERT
INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'example.com','ns1.outerin.net','NS',86400,NULL);
INSERT
INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'example.com','ns2.outerin.net','NS',86400,NULL);
INSERT
INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'www.example.com','192.168.1.100','A',120,NULL);
INSERT
INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'mail.example.com','192.168.1.252','A',120,NULL);
INSERT
INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'localhost.example.com','127.0.0.1','A',120,NULL);
INSERT
INTO records (domain_id, name, content, type,ttl,prio) VALUES (1,'example.com','mail.example.com','MX',120,25);

Now try the command again. Your should see a returned record, success; we are getting result and our setup is working.

In the next part I’ll be increasing the security and getting the DNS to start up automatically. I’ll also be looking at the master/salve configuration and seeing how it ties together.

Thanks to Norbert @ Linux Networks for getting me over the last hurdle. Check out the following website for further information.

http://www.linuxnetworks.de
http://www.powerdns.com
http://www.freetds.org
http://software.opensuse.org
http://download.opensuse.org/repositories

Regards

Tobi

Categories: DNS, Hosting Tags: