kolmapäev, 30. detsember 2009

Kes, kuna, kuidas, milleks ja kust (IP aadressiga) on andmebaasi küljes

Abiks järgnev päring

SELECT dm_exec_sessions.session_id, dm_exec_sessions.status
, dm_exec_sessions.login_name, dm_exec_sessions.original_login_name
, dm_exec_connections.net_transport
, dm_exec_connections.connect_time
, dm_exec_sessions.login_time
, dm_exec_connections.protocol_type
, dm_exec_connections.client_net_address
, dm_exec_connections.client_tcp_port
, dm_exec_connections.auth_scheme
, dm_exec_sessions.HOST_NAME, dm_exec_sessions.NT_DOMAIN
, dm_exec_sessions.program_name, dm_exec_sessions.client_interface_name
, dm_exec_sessions.language, dm_exec_sessions.client_version
, dm_exec_requests.command, dm_exec_requests.wait_type, dm_exec_requests.wait_time, dm_exec_requests.wait_resource
FROM sys.dm_exec_sessions
JOIN sys.dm_exec_connections ON (dm_exec_sessions.session_id = dm_exec_connections.session_id )
INNER JOIN master..sysprocesses ON (dm_exec_sessions.session_id = sysprocesses.SPID)
LEFT JOIN sys.dm_exec_requests ON (dm_exec_sessions.session_id = dm_exec_requests.session_id)
WHERE DB_NAME(sysprocesses.dbid) = DB_NAME()
--AND dm_exec_sessions.status != 'sleeping'


dm_exec_sessions.session_id põhjal võib teha KILL sellele ühendusele

dm_exec_sessions.program_name saad seada Web.Config faili ConnectionStringis Application Name parameetriga niimoodi

connectionString="Data Source=SQL2008SERVER;Min Pool Size=2;Application Name=MINURAKENDUS; ...

reede, 18. detsember 2009

GridView TemplateField veeru päise muutmine nii, et sortimine jääks alles

TemplateFieldil võib päise ja sorteerimise kirjeldada nii

Kui vaja nüüd veeru päise teksti dünaamiliselt muuta nii, et sorteerimise võimalus alles jääks
siis tee eraldi HeaderTemplate, kuhu poeta Linkbutton, mille CommandName on "Sort" ja CommandArgument on see andmebaasi väli mille järgi sorteerida tahad

Kui nüüd vaja päise teksti muuta, saad teha nii kusjuures sortimine jääb alles

protected void GridViewKolijad_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
LinkButton ud = (LinkButton)e.Row.FindControl("LinkButtonVana");
if (ud != null)
{
ud.Text = this.RadioButtonListSisse.SelectedValue == "0" ? Resources.Resource.NewContract : Resources.Resource.PreviousContract;
}
}
}

reede, 4. detsember 2009

II astme SQL süstimise tõkestamine reapiiranguga

Üks viis kuidas tõkestada SCRIPT, IFRAME, FORM, BODY ja muude murdskriptimisvõimaluste lisamist andmebaasi on panna string tüüpi väljade peale reapiirangud näiteks LIKE operandi kasutades

ALTER TABLE [dbo].[HD_PROBLEMS] WITH CHECK ADD CONSTRAINT [CK_HD_PROBLEMS_SQL_INJECTION] CHECK ((NOT [problemDescription] LIKE '%<_%')) Siin LIKE '%<_%' tähendab kõik stringid kus < järel on mingi character sümbol (ka tühik)


ALTER TABLE [dbo].[HD_PROBLEMS] WITH CHECK ADD CONSTRAINT [CK_HD_PROBLEMS_SQL_INJECTION] CHECK ((NOT [problemDescription] LIKE '%<[A-Z]%'))

Siin LIKE '%<[A-Z]%' kõik stringid kus < järel on mingi täht A kuni Z

ALTER TABLE [dbo].[HD_PROBLEMS] WITH CHECK ADD CONSTRAINT [CK_HD_PROBLEMS_SQL_INJECTION] CHECK ((NOT [problemDescription] LIKE '%<[ASIDBMFH/]%'))

Siin LIKE '%<[ASIDBMFH/]%' tähendab kõik stringid kus < järel on mingi sümbol nimekirjast ASIDBMFH/
Koos NOT-iga saame lausendi mis kontrollib "ei ole mustas nimekirjas".
Standardid soovitavad muidugi kasutada valge nimekirja kontrollimist.

Kuidas töötab

Kui nüüd üritatakse XSS-i kirjutada andmebaasi välja sisse (II astme rünnak)



siis reapiirang asub tegevusse ja andmeid muuta ei lubata

neljapäev, 26. november 2009

String tüüpi muutuja polsterdamine SQL süstimise vastu

Kui ei pääse üle ega ümber sellest, et vaja dünaamiline SQL kirjutada ja sp_executesql kasutada ei saa siis string tüüpi muutujad (VARCHAR, NVARCHAR, CHAR jne) polsterda järgmiselt:

REPLACE(@otsiparam,'''','''''') ning enne ja pärast seda veel kolmed ülakomad

näiteks niimoodi:

DECLARE @os NVARCHAR(MAX)
SET @otsiparam=LTRIM(RTRIM(ISNULL(@otsiparam,'')) --juhuks, kui tühikud ees ja taga võivad probleemiks olla ning parameeter võib ka NULL olla.
SET @os='SELECT TOP 1 NIMED.NIMI FROM DBO.NIMED WITH(NOLOCK) WHERE NIMED.ID = '''+REPLACE(@otsiparam,'''','''''')+''''
EXECUTE (@os)

Kui vaja ainult ühte rida andmebaasist kätte saada siis mõtekas TOP 1
SELECT lausesse lisada. Aitab OR 1=1 rünnakute vastu.

See muutuja, mida EXECUTE lausega käima tõmbad võiks olla NVARCHAR(MAX) tüüpi, siis ei jõuta seda ülakomasid ''''''' täis ajada, ennem astuvad võrgu piirangud vahele.

C# käib polsterdamine nii
public string Polsterda(string inputSQL)
{
return inputSQL.Replace("'", "''");
}

kolmapäev, 18. november 2009

Võõra XmlNode panemine teise XmlDocument -i sisse

Kõik XmlNode tüüpi asjad on konkreetselt seotud selle XmlDocument-iga, mille külge nad tehti.

Kui nüüd tahta "võõrast" XmlNode panna teise XmlDocument-i sisse tuleb see importida

//algne XmlDocument
XmlDocument res = new XmlDocument();
XmlElement elem = res.CreateElement("SkoorResult");
res.AppendChild(elem);

// see "nd" on nüüd see "võõras" node, mille kuskilt mujalt saame
TimeZoneInfo localZone = TimeZoneInfo.Local;
TimeSpan vahe = localZone.GetUtcOffset(System.DateTime.Now);

XmlNode nd = MakeRequest(nod,vahe);


//impordime sisse
XmlNode nodeToMove = res.ImportNode(nd, true);
res.DocumentElement.AppendChild(nodeToMove);

neljapäev, 5. november 2009

Veebilehe ViewState suuruse näitaja Firefoxile

Selline kaval asi on olemas:
https://addons.mozilla.org/en-US/firefox/addon/5956

Kui avad mingi ASPX lehe, rehkendab lehe allaäärde veebilehe ViewState suuruse.
ViewState on teatavasti see info, mida IIS lehele kaasa paneb, et seal veebilehe elementide "mälu" hoida. Mida suurem ViewState seda "paksem" leht, mida väiksem ViewState seda nobedamini leht kohale tiritakse.

Veebirakenduse puhul tegemist sisuliselt dilemmaga. Kas küsida iga kord andmed andmebaasist uuesti (koormab rohkem andmebaasiserverit) või kord juba küsitud andmed panna lehe ViewState(mis teeb lehe mahult suuremaks ja närib rohkem ribalaiust ära).

kolmapäev, 28. oktoober 2009

Ära näita sirviku JavaScriptile küpsiseid

kui sul seda vaja ei ole, ehk lisa web.config faili rida httpOnlyCookies="true"
saad murdskriptimise vastu võidelda, sirviku Javascript ei pääse enam küpsisele ligi (sõltub sirvikust ja selle versioonist)
ja kui vaja ka et küpsised läheksid läbi SSL-i võid panna ka selle jupi juurde
requireSSL="true"


reede, 23. oktoober 2009

XML andmete näitamine TreeView ja XmlDataSourcega

Andmebaasis on XML väli kuhu paneb sisse igasugu andmeid, peamiselt logimisinfot mille jaoks iga kord tabelisse eraldi tulpa teha ei viitsi. XML andmete stuktuur kuidas kunagi
mõnel rohkem
mõnel vähem
ja tulevikus võib vajadusel juurde lisada.

Ekraanil hierarhiliste andmete näitamiseks sobib hästi TreeView nimeline control, XML andmed salvestab XmlDataSourceTähele peab panema, et XmlDataSource on EnableCaching vaikimisi True, kuna vaja andmebaasist dünaamiliselt iga kord uusi andmeid näidata tuleb
EnableCaching="false" seada

Vaikmisi TreeView seab andmed XML elementde külhge, et ekraanil näitab ainult
Options, AcceptedUser ja RELATED_CONTRACT teksti nii nagu XML andmete tippude nimed on, kuna see mis andmebaasi XML väljast tuleb võib igakord erinev olla siis
ontreenodedatabound="TreeViewExtraInfo_TreeNodeDataBound" eventis tuleb natuke käsitsitööd teha, näiteks nii:

protected void TreeViewExtraInfo_TreeNodeDataBound(object sender, TreeNodeEventArgs e)
{
try
{
System.Xml.XmlElement cdf = (System.Xml.XmlElement)e.Node.DataItem;

if (cdf.Name == "Options") //juurelement
{
e.Node.Text = Resources.Resource.ExtraInfo;
}
else
{
if (cdf.InnerXml != "")
{
try //kui ta sellist node nimetust ei leia resursi tekstidest, võtame NODE enda nime
{
e.Node.Text = HttpContext.GetGlobalResourceObject("Resource", cdf.Name).ToString()+ " " + cdf.InnerText;
}
catch (SystemException ex)
{
e.Node.Text = cdf.Name + " " + cdf.InnerText;
}
}
}
if (cdf.HasAttributes) //kui on atribuute siis lisame elemendile ühe alamtipu
{
for (int i = 0; i < cdf.Attributes.Count; i++)
{
TreeNode db;
try
{
//kas ressursi tekstides on tipu elemendi kirjeldus olemas
db = new TreeNode(HttpContext.GetGlobalResourceObject("Resource", cdf.Attributes[i].Name).ToString() + " " + cdf.Attributes[i].Value);
}
catch (SystemException ex)
{
db = new TreeNode(cdf.Attributes[i].Name + " " + cdf.Attributes[i].Value);
}
e.Node.ChildNodes.Add(db);
}
}
}
catch (SystemException ex)
{
this.CustomValidator1.ErrorMessage = ex.Message;
this.CustomValidator1.IsValid = false;
}
}

Ekraanile aga paistab:


AcceptedUseri all on atribuutidest tehtud lisatipud

Andmete külgepanemine käib XmlDataSourceExtraInfo.Data property kaudu
this.XmlDataSourceExtraInfo.Data = this.ApplicationOptions(this.application_id);
this.TreeViewExtraInfo.DataBind();

siin this.ApplicationOptions(this.application_id) tagastab XML stringi mille andmebaasi XML väljast loen

public string ApplicationOptions(int applicationId)
{
string retu = "";
using (SqlConnection konn = new SqlConnection(Configuration.ConnectionString))
{

SqlCommand komm = new SqlCommand("SELECT [dbo].[APPLICATION_OPTIONS_KUIDO_S](" + applicationId.ToString() + ")", konn);
komm.CommandType = CommandType.Text;
konn.Open();
Object ret = komm.ExecuteScalar();
if (!ret.Equals(DBNull.Value))
{
retu = ret.ToString();
}
konn.Close();
}
return retu;
}

teisipäev, 20. oktoober 2009

GridView tulba peitmine andmebaasi välja põhjal

Kui vaja teha mingi PIVOT päring andmebaasist või üldse juhtudel kus andmebaasist võib iga kord erinevate tulpade arvuga Tabular Data Stream (TDS) vastu tulla ning vaja seda ekraanil kuvada nii, et mõnda tulpa ei näitaks siis üks asja lahendus on GridView kasutamine AutoGenerateColumns="True" seadistusega.

Kuna GridView sisse saab teha igasugu tüüpi tulpasid siis põhimõte on see, et kontrollime, kas on teatud tüüpi tulp. Näiteks kontrollime, kas on BoundField tüüpi tulp ja kui on siis kas DataField langeb otsitavaga kokku.

///
/// tagastab GridView asp:BoundField tüüpi tulba indeksi DataField nime põhjal
///

///
/// fieldName on DataFieldi väli mida otsida
///
public int GetGridColumnIndex(GridView grd, string fieldName)
{
for (int i = 0; i < grd.Columns.Count; i++)
{
DataControlField field = grd.Columns[i];
//üritame pöörata BoundField-iks
BoundField bfield = field as BoundField;
//kui on BoundField ja DataField langeb ka kokku tagastame tulba indeksi
if (bfield != null && bfield.DataField.ToUpper() == fieldName.ToUpper())
{
return i;
}
}
return -1;
}


Tulba peitmine, PEIDATULP on see TDS tulp mida näidata ei taha

//leiame selle tulba numbri, mida ei tohi näidata
int tlnr = GetGridColumnIndex(this.GridViewKeeled, "PEIDATULP");
if (tlnr != -1)
{
this.GridViewKeeled.Columns[tlnr].Visible = false;
}

kolmapäev, 14. oktoober 2009

BULK INSERT tekstifailist CLR-i kasutades

Sai kogemata SQLSERVER 2008 Web Edition maha müüdud ja siis avastatud, et Integration Services selle versiooni sees ei olegi. Kokkuvõttes tuleb asjad ise teha ja loeme nüüd BULK INSERT käsuga otse tekstifailist:


using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void HansaImport(SqlString fail, SqlString kataloog, SqlString sihttabel, SqlInt32 kustutafail)
{
//teeme sisendparameetrite kontrolli ja lõikame lõpud maha
string siht = Convert.ToString(sihttabel);
siht=siht.Substring(0, (siht.Length > 30 ? 30 : siht.Length));
string kat = Convert.ToString(kataloog);

kat = kat.Substring(0, (kat.Length > 30 ? 30 : kat.Length));
string fai = Convert.ToString(fail);
fai = fai.Substring(0, (fai.Length > 20 ? 20 : fai.Length));
string impafail = kat + fai;
if (System.IO.File.Exists(impafail))
{
using (SqlConnection konn = new SqlConnection("Context connection=true"))
{
SqlCommand komm = new SqlCommand("TRUNCATE TABLE " + siht + "; BULK INSERT " + siht + " FROM '" + impafail + "' WITH (FIELDTERMINATOR ='\t',ROWTERMINATOR ='\n', BATCHSIZE = 10000)", konn);
konn.Open();
komm.ExecuteNonQuery();
konn.Close();
if (kustutafail == 1)
{
System.IO.File.Delete(impafail);
}
}
}
else
{
throw new SystemException("CLR Error !! Missing file: " + fai + " in directory: " + kat);
}
}
}


Kui nüüd värk käivitada Management Studio alt siis kõik OK aga kui panna jooksma kui andmebaasi töö tuleb selline viga

Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row

Tekstifailis on kuupäev kujul 23.10.2009

Et asi andmebaasi tööna jooksma saada anname temale kuupäeva formaadi ette
SET DATEFORMAT DMY
EXECUTE [dbo].[HansaImport]
@fail='arved.txt'
,@kataloog='D:\HANSA_IMPORT\'
,@sihttabel='[dbo].[HANSA_ARVED_TEMP]'
,@kustutafail=0

SQL SERVER Agent kasutab SQL SERVERi enda kuupäeva seadeid asjadest aru saamiseks

reede, 9. oktoober 2009

Andmebaasi tööde ülevaade

Selleks, et mingi SQL SERVER Agent-i töö käiks peab
1. Töö ise olema lubatud
2. Töö enda plaanur olema lubatud

Kuna mõnikord unustad selle märkeruudu "Enabled" peale sättida siis abiks SP mis teeb ülevaate SQL Agenti andmebaasi töödest.

ENABLED väli näitab kas töö on peatatud
SCHEDULE_ENABLED väli näitab kas töö plaanur on peatatud

[dbo].[SQLSERVERAGENTDATETIME_KUIDO] funktsiooni ma olen kirjeldanud
varasemalt siin http://kuidoveeb.blogspot.com/2009/04/sql-server-agent-kuupaeva-funktsioon.html

Parameeter @job_names võimaldab filtreerida töö nime alguse järgi

-- =============================================
-- Description: Andmebaasi tööde nimekiri
-- =============================================
CREATE PROCEDURE [dbo].[WINTIME_JOBS_KUIDO_S]
@job_names NVARCHAR(128)=N'MINUTOOD'
WITH EXECUTE AS 'DBO' --käivitame teatud kasutaja õigustes kuna pole mõtet and igaühele otse tabelitele juurdepääsu
AS
BEGIN
SET NOCOUNT ON
DECLARE @err INT
IF RIGHT(@job_names,1) <> '%'
SET @job_names=@job_names+'%'
--OTSIME KÕIGEPEALT SOBIVAD TÖÖD VÄLJA (filter nime alguse järgi)
DECLARE @tood TABLE (job_id UNIQUEIDENTIFIER PRIMARY KEY, job_name NVARCHAR(128) COLLATE DATABASE_DEFAULT, enabled TINYINT,
job_owner NVARCHAR(128) COLLATE DATABASE_DEFAULT NULL )
INSERT INTO @tood (job_id, job_name, [enabled] , job_owner)
SELECT sj.JOB_ID, sj.NAME, sj.[enabled],su.name FROM [msdb]..sysjobs sj
LEFT JOIN msdb..[SYSUSERS] su ON (sj.owner_sid = su.sid )
WHERE sj.name LIKE @job_names
--TEEME ÜLEVAATE
SELECT ISNULL(b.job_owner,'') AS job_owner, b.job_name, b.job_id, b.[enabled]
,[dbo].[SQLSERVERAGENTDATETIME_KUIDO](c.next_run_date,c.next_run_time) AS NEXT_RUN_TIME
,a.step_name, a.subsystem, a.command, a.database_name
,a.step_id, a.step_name, c.schedule_enabled
,Hist.[MESSAGE] AS LAST_RUN_MESSAGE, Hist.LAST_RUN_TIME
,Hist.[RUN_DURATION] AS LAST_RUN_DURATION, Hist.RUN_STATUS AS LAST_RUN_STATUS
FROM msdb..sysjobsteps a
INNER JOIN @tood b ON ( a.job_id =b.job_id )
INNER JOIN (SELECT sc.job_id , sc.next_run_time, sc.next_run_date, ssc.[enabled] AS schedule_enabled
FROM msdb..sysjobschedules sc --uurib ka schedule on enabled
INNER JOIN [msdb]..[sysschedules] ssc ON (sc.[schedule_id] = ssc.[schedule_id])
WHERE EXISTS (SELECT job_id FROM @tood Tli WHERE Tli.job_id = sc.job_id )
) c ON (a.job_id = c.job_id)
INNER JOIN
(
SELECT DISTINCT J1.JOB_ID, J1.[MESSAGE],
[dbo].[SQLSERVERAGENTDATETIME_KUIDO](J1.RUN_DATE,J1.RUN_TIME) AS LAST_RUN_TIME,
J1.RUN_STATUS, J1.RUN_DURATION
FROM msdb.dbo.sysjobhistory J1 WHERE J1.step_id=0
AND job_id IN (SELECT job_id FROM @tood Tli )
AND ( [dbo].[SQLSERVERAGENTDATETIME_KUIDO](J1.RUN_DATE,J1.RUN_TIME) =
( SELECT MAX([dbo].[SQLSERVERAGENTDATETIME_KUIDO](J2.RUN_DATE,J2.RUN_TIME) )
FROM msdb.dbo.sysjobhistory J2 WHERE J1.[job_id] = J2.JOB_ID AND J2.step_id=0) )
) Hist ON (a.job_id = Hist.JOB_ID )
ORDER BY B.JOB_NAME
/*
LAST_RUN_STATUS
0 Failed
1 Succeeded
2 Retry (step only)
3 Canceled
4 In-progress message
5 Unknown
*/
END

neljapäev, 1. oktoober 2009

XML välja sisu ilusaks ajamine peale sql:variable-ga mudimist

Selline juhtum, kui on vaja SQL SERVER-i XML muutujat vahepeal muuta no näiteks
DECLARE @aop XML, @lep INT, @relcon NVARCHAR(2000)

SET @relcon=''+CAST(@contractId AS NVARCHAR(20))+''

SET @lep = @aop.value('/RELATED_CONTRACT[1]', 'INT')
IF @lep IS NULL --KUI RELATED_CONTRACT on puudu, lisame vastava NODE
SET @aop.modify('insert text{sql:variable("@relcon")} as last into (/Options)[1]')

kui nüüd SQL SERVER manageriga seda @aop sisu vaadata on seal '<' asemel
mis ei ole üldsegi ilus, et see asi korda saada tuleb stringitöötlust teha, XML muutuja pöörata NVARCHAR(MAX), muuta ära ja pöörata XML-iks tagasi


Kui tahad XML välja RAISERRORIGA ekraanile lasta, siis tuleb samuti stringitöötlust teha

SET @relcon = REPLACE(CAST(@aop AS NVARCHAR(4000)),'<','_')
RAISERROR('XML info %s',16,1,@relcon)

ASP.NET tõlgendab ju '<' algavaid asju kui HTML-i elemente mis tegelikult ongi õige

esmaspäev, 21. september 2009

Delegaadil põhinev andmevahetus usercontrolite vahel

Tegelikult ei soovitata nii teha aga kui harva tuleb sellised asju ette siis hea lihtne meeles pidada.
Definitsioonide nimetused võivad siis postituses segamini olla.
Veebilehel on mitu usercontroli ja tahad, et näiteks kui GridView peal klikid seda Select nuppu siis tahad, et selle tulemusena mingil teisel usercontrolil midagi juhtuks.

Gridview Select nupu saab teha niimoodi

Usercontroli Code-behindis defineerib delegaadi ja eventi mille külge saavad teised controlid end külge pookida, kui asja peaks olema. UserControli nimi on näiteks OtsiKohamaara

public event ValitiKorter KorterValiti; //see event saadab välja ValitiKorter(int indeks) delegaati
public delegate void ValitiKorter(int indeks);


GridView SelectedIndexChanged SelectedIndexChanged event, mis hakkab seda delegaati välja saatma:

protected void GridViewKorterid_SelectedIndexChanged(object sender, EventArgs e)
{
GridViewRow se = this.GridViewKorterid.SelectedRow;
if ( se != null)
{
if (KorterValiti != null) // kas on keegi ennast külge pannud, et sellele SelectedIndexChanged reageerida
{
KorterValiti(Convert.ToInt32(this.GridViewKorterid.SelectedDataKey.Value));
}
}
}


Kuida asja tarbida teise veebilehe peal, kõigepealt registreerime ennast delegaati vastu võtma.

protected void Page_Load(object sender, EventArgs e)
{
//OtsiKohamaara1 on nüüd see UserControl lehe peal mille Select nupu kliki tahame kinni püüda
//see tuleb iga kord PostBackist sõltumata, muidu unustab ära
this.OtsiKohamaara1.KorterValiti += new UserControl_OtsiKohamaara.ValitiKorter(OtsiKohamaara1_KorterValiti);
if (!IsPostBack)
{
}
}

ja meetod, mis selle delegaadiga tegelema hakkab.

// kui OtsiKohamaara korter valitakse, siis tuleb sealt delegaat
void OtsiKohamaara1_KorterValiti(int indeks)
{
//indeks on nüüd see int väärtus, mis usercontroli poolt teele saadetakse
// ja siin saab juba asju edasi teha
this.LiteralFlatId.Text = indeks.ToString();
}

teisipäev, 25. august 2009

GridView ridade kokkusummeerimine Contentpage ja UpdatePanel-i sees .NET Framework 3.5 SP1

Kui on Masterpage sees asp:Content lehekülg mille see on UpdatePanel ja selle sees GridView võib juhtuda, et
GridView RowDataBound kutsutakse kaks korda välja, kusjuures mõnel serveril töötab korralikult mõnel aga mitte, täitsa kuidas juhtub.
Kui nüüd summerida GridView RowDataBound eventis mingeid väärtusi kokku võib saada topelt tulemuse ja juhtub see täiesti suvaliselt

if (e.Row.RowType == DataControlRowType.DataRow)
{
this.tsumma += Convert.ToDecimal(((System.Data.DataRowView)e.Row.DataItem)["total_summa"]);
}
if (e.Row.RowType == DataControlRowType.Footer)
{
e.Row.Cells[2].Text = Resources.Resource.Total;
e.Row.Cells[3].Text = String.Format("{0:F2}", this.tsumma);
}

Siin võib juhtuda, et summa on tegelikult kahekordselt arvutatud.

Lahendusena võib summerimise tuua GridView DataBound eventisse
this.tsumma=0;
foreach (GridViewRow rida in this.GridViewArved.Rows)
{
if (rida.RowType == DataControlRowType.DataRow)
{
Label rs = (Label)rida.FindControl("LabelArveSumma");
if (rs != null)
{
this.tsumma += Convert.ToDecimal(rs.Text.Trim());
}
}
}
if (this.GridViewArved.FooterRow != null)
{
this.GridViewArved.FooterRow.Cells[2].Text = Resources.Resource.Total;
this.GridViewArved.FooterRow.Cells[3].Text = String.Format("{0:F2}", this.tsumma);
}


LabelArveSumma on GridView TeplateField-is olev WebControl
<asp:TemplateField SortExpression="total_summa" HeaderText="<%$ Resources:resource, InvoiceTotal %>">
<ItemTemplate>
<asp:Label ID="LabelArveSumma" runat="server"
Text='<%# Eval("total_summa", "{0:F2}") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
Blogged with the Flock Browser

kolmapäev, 29. juuli 2009

Sys.Net.WebRequest klassiga kliendi sertifikaadi küsimine kasutades Request.ClientCertificate meetodit

Vaja lisada andmete sisestusvormile nupp, millega saab osa vormil nõutavaid andmeid lugeda ID-kaardi pealt, kuid nii, et vormi teistele väljadele sisestatud info jääks peale ID-kaardilt andmete lugemist alles(ei tee tervele lehele Postbacki). See asi on võimalik lahendada .NET 3.5 AJAX-i Sys.Net.WebRequest klassi kasutades

Vorm näiteks selline, kus isikukoodi, ees- ja perekonnanime võib lugeda ID-kaardi pealt ja muu info tuleb käsitsi sisestada



ID-kaardilt saame andmed kätte tehes algselt lehelt WebRequest.invoke() GET requesti päringu lehele Idkaart.aspx, kus Request.ClientCertificate meetodiga loeme
ID-kaardilt andmed ja saadame nad tagasi püstkriipsuga eraldatud stringijadana Response.Write("Isikukood|Perekonnanimi|Eesnimi");
IIS-i poolt tuleb Idkaart.aspx lehel peale seada, et Accept Client certificate, siis pöördumisel
Idkaart.aspx poole küsitakse kliendi sertifikaati, ehk ID-kaardi puhul tuleb PIN1 sisestada

NB! Kui kasutatakse Sertifitseerimiskeskuse serte, siis nii JUUR-SK kui ka KLASS3-SK serdid peavad olema õieti paigaldatud, vastasel juhul Request.ClientCertificate ei pruugi tööle hakata

Idkaart.aspx lehe sisu selline, sealt loeme ID-kaardi andmed

public partial class IdKaart : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string inf="";
try
{
//küsime kliendi sertifikaati
HttpClientCertificate sert = Request.ClientCertificate;
if (sert.IsPresent) //kui sertifikaat on olemas
{
if (System.DateTime.Now < sert.ValidUntil) //kas kehtib veel
{
String unparsed = sert.Subject;
System.Text.RegularExpressions.Regex re = new Regex("SERIALNUMBER=(\\d{11})");
if (re.IsMatch(unparsed))
{
if (re.Match(unparsed).Groups[1].Value.Length == 11) //isikukood peab olema 11 sümbolit pikk
{
inf = re.Match(unparsed).Groups[1].Value + "|"; //isikukood
}
}
System.Text.RegularExpressions.Regex rename = new Regex("SN=(.*?),\\s+G=(.*?),");
if (rename.IsMatch(unparsed))
{
inf += rename.Match(unparsed).Groups[1].Value+"|"; //perekonnanimi
inf += rename.Match(unparsed).Groups[2].Value; //eesnimi
}
}
}
}
catch (SystemException ex)
{ }
//tagastame eraldatud stringijada isikukood|perekonnanimi|eesnimi
Response.Clear();
Response.BufferOutput = false;
Response.ContentType = "text/plain";
Response.ContentEncoding = System.Text.ASCIIEncoding.Default;
Response.Write(inf);
Response.End();
}
}

leht XMLHttpParing.aspx, kus andmeid küsime näeb välja selline, kasutada tuleb Javaskripti, mis WebRequest.invoke() meetodiga pöördub lehelt IdKaart.aspx andmeid lugema ja kui on sealt
andmed kätte saanud, siis täidab osad sisestusväljad ära ja keelab nende edasise kasutamine


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="XMLHttpParing.aspx.cs" Inherits="ASP_DEMO.XMLHttpParing" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>XMLHttpPäring</title>
<script type="text/javascript">
var xmlreq;
function pagLoad() {
try {
var webRequest = new Sys.Net.WebRequest();
webRequest.set_url("IdKaart.aspx");
webRequest.set_httpVerb("GET");
webRequest.add_completed(completedHandler);
webRequest.invoke();
}
catch (err)
{ }
}
function completedHandler(result, eventArgs) {
if (result.get_responseAvailable()) {
var vastus = new Array();
vastus = result.get_responseData().split("|");
if (vastus.length == 3) {
var nimi = document.getElementById("<%= TextBoxPerenimi.ClientID %>");
nimi.value = vastus[1];
nimi.disabled = true; //kui tuleb andmeid ID-kaardilt, siis keelab edasise tekstivälja muutmise ära
nimi = document.getElementById("<%= TextBoxEesnimi.ClientID %>");
nimi.value = vastus[2];
nimi.disabled = true;
nimi = document.getElementById("<%= TextBoxIsikukood.ClientID %>");
nimi.value = vastus[0];
nimi.disabled = true;
nimi = document.getElementById("<%= ButtonIdkaart.ClientID %>");
nimi.disabled = true;
}
}
}
</script>

</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel runat="server" ID="UpdatePanel1">
<ContentTemplate>
<table>
<tr>
<td>Isikukood&nbsp;<asp:TextBox ID="TextBoxIsikukood" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td>Perekonnanimi&nbsp;<asp:TextBox ID="TextBoxPerenimi" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td>Eesnimi&nbsp;<asp:TextBox ID="TextBoxEesnimi" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td style="width:200px">Muu info(tekst, mis ID kaardilt andmete küsimise järel jääb vormile alles<asp:TextBox ID="TextBoxMuu" MaxLength="400" Rows="4" Columns="70"
runat="server" TextMode="MultiLine"></asp:TextBox>
</td>
</tr>
</table>
<div>
<asp:Button ID="ButtonIdkaart" CausesValidation="false" runat="server"
Text="Loe andmed ID-kaardilt" />
<asp:Button ID="ButtonEdasi" runat="server" Text="Edasi" />
</div>
</ContentTemplate>
</asp:UpdatePanel>

</form>
</body>
</html>


code-behind XMLHttpParing.aspx lehele
public partial class XMLHttpParing : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//paneme kliendi poolse javascripti külge, tuleb kasutada return pagLoad(),
// kui ainult pagLoad() onClick eventile külge panna, teeb leht Postbacki ja
// webRequest.invoke()-iga loetud andmed korra vilksatavad ekraanil ja siis kaovad
this.ButtonIdkaart.Attributes.Add("onClick", "return pagLoad()");
}

}





pagLoad() on see isetehtud Javaskripti funktsioon, mille välja kutsume ja mis selle AJAX-I XMLHttpRequest päringu ära teeb.
function completedHandler() on see Javaskripti funktsioon, mis IdKaart.aspx lehelt info vastu võtab, töötleb ja kontrollib neid ning viib saadud andmed vormile.

Pikemalt on Windowsi Certificate Services Client-ist mille kaudu ID-kaardi majandmine
käib juttu siin.

http://technet.microsoft.com/en-us/library/cc700848.aspx




Blogged with the Flock Browser

neljapäev, 23. juuli 2009

URL RequestFiltering koos ReportViewer Controliga IIS7 peal

IIS7 on veebirakendustele selline tore sisseehitatud võimalus filtreerida GET päringuid URL andmete järgi, ehk rakenduse web.config failis, saab requestFiltering filtering osas ära määrata, kui pikk saab olla maksimaalne
URL ja kui pikk saab olla QUERYSTRING. Aitab näiteks SQL injektsiooni rünnakute vastu.
Kui on ka kasutusel ReportViewer aruannete tegemiseks, tuleb arvestada, et see ReportViewer ise teeb ka palju GET päringuid, mis isenesest võivad olla päris pika QUEYSTRING-iga näiteks
URI: /Reserved.ReportViewerWebControl.axd?Mode=true&ReportID=56afacf3f4c74cd69af397d2b8eefc0b&ControlID=a64ab41370cf4a28ba5967b952cf9038&Culture=1061&UICulture=1061&ReportStack=1&OpType=ReportImage&StreamID=148c7b15-8020-4ce4-9e17-a48043495af8

Otstarbekam on nüüd määrata eraldi web.configis reegel location elemendiga ReportViewerile näiteks niimoodi:


kolmapäev, 22. juuli 2009

Muutujat kasutava SQL päringu kiirendamine OPTION(RECOMPILE) kasutamisega

Üks päring millega päev otsa vaeva nägin. Tehtud täitsa mõistlik SP, mille sees üks päring

DECLARE @apref VARCHAR(1)
SET @apref='C'

SELECT ACCOUNT.ID FROM DBO.ACCOUNT WHERE NOT EXISTS
( SELECT fd.[inv_no] FROM [dbo].[Cust_ Ledger Entry] fd WHERE
fd.[inv_no] = @apref+CAST(ACCOUNT.ID AS VARCHAR(30)) ) AND ACCOUNT.
W_SENT IS NOT NULL

mis töötab aga jube aegalselt

kui päring muuta lihtsalt ilma muutuja kasutamiseta päringuks

SELECT ACCOUNT.ID FROM DBO.ACCOUNT WHERE NOT EXISTS
( SELECT fd.[inv_no] FROM [dbo].[Cust_ Ledger Entry] fd WHERE
fd.[inv_no] = 'C'+CAST(ACCOUNT.ID AS VARCHAR(30)) ) AND ACCOUNT.
W_SENT IS NOT NULL

on asi kiire
Probleem selles, et SQL SERVER-i optimisaator teeb tervele SP-le optimiseerimise ja
SELECT lause koha peal ta ei tea mis on @apref väärtus ja üritab seda pimesi arvata

Üks võimalus on teha dünaamiline SQL aga parem on kasutada OPTION(RECOMPILE) SELECT lause juures

SELECT ACCOUNT.ID FROM DBO.ACCOUNT WHERE NOT EXISTS
( SELECT fd.[inv_no] FROM [dbo].[Cust_ Ledger Entry] fd WHERE
fd.[inv_no] = @apref+CAST(ACCOUNT.ID AS VARCHAR(30)) ) AND ACCOUNT.
W_SENT IS NOT NULL OPTION(RECOMPILE)

sel juhul optimisaator vaatab muutja @apref väärtust päringu tegemise hetkel ja päring läheb kiireks

Asja lahendamise juures olid abiks SQLMONSTERi inimesed
http://www.sqlmonster.com/Uwe/Forum.aspx/sql-server-performance/331/Variable-in-SELECT-expression-causes-query-degradation

reede, 3. juuli 2009

Andmebaasi stuktuuri kaitsmine VIEW DEFINITION õiguse keelamisega PUBLIC rollil

Iga kasutaja, mis MS SQL SERVER-il tehakse ja kellele antakse ligipääs mingile andmebaasile pannaks vaikimisi ka selle andmebaasi PUBLIC rolli. Mille tulemusena saab kasutaja näha, mis protseduurid ja tabelid selles andmebaasis olemas on, ehk näha andmebaasi struktuuri kirjeldust.

Rakenduse toimimiseks ei pruugi aga andmebaasi struktuuri kirjelduse teada olemine üldse vajalik olla. Seda saab piirata, kui keelata andmebaasi PUBLIC rollil VIEW DEFINITION õigus.

DENY VIEW DEFINITION TO public

Lõpeb nüüd asi sellega, et kui kasutaja baasi sisu vaatab ei näe ta sealt midagi. Avab näiteks Management Studioga baasi aga seal ei näita baasi struktuurist mitte kui midagi

Isegi, kui temale on andmebaasisi DB_OWNER õigused antud, siis saab ta näha vaid tabelite sturkuuri aga ei saa tabelite struktuuri muuta.
Saab veateate Tabel TABELINIMI is set to read only, user doesn't have enough rights on this table

Kõrvalnäht, mis kaasneb Visual Studio2008 kasutamisega on see, et kui projektis on datasetid (xsd failid) siis seal sees tabeladapterite muutmisel ei näidata näiteks enam salvestatud protseduuride nimekirja.

Õiguse saab tagasi panna
GRANT VIEW DEFINITION TO public


kolmapäev, 10. juuni 2009

ReportVieweri kasutamine IIS7 ja Windows Server 2008 korral

Kui ReportVieweri väljatrükil ekraanil on "tühi" või ei tule üldse ette


siis asja tööle seadmiseks

Variant A:
tuleb IIS Magnageriga (Application Pools) rakenduse basseini Managed Pipeline Mode seada "Classic" peale




Variant B tuleb basseini Intergated Mode korral rakenduse HandlerMappings menüüst käsitsi Add Managed Handler menüüpunkti abil ReportVieweri handler lisada, selleks:

Request Path ja Name koha peale kirjuta Reserved.ReportViewerWebControl.axd
Type: vali menüüst Microsoft.Reporting .., Microsoft.ReportViewer ..
Blogged with the Flock Browser

reede, 29. mai 2009

SQL SERVER UDF funktsiooni teksti sisust parameetri vaikeväärtuse teadasaamine

Kui süsteemis on kasutusel meetod, kus mingi asja käitumine sõltub näiteks UDF funkstiooni parameetri väärtusest ja nüüd vaja teada
saada, kuidasmoodi see parameeter on seatud saab kasutada sellist

Funktsiooni päis ise, mille parameetrit teada tahame

ALTER FUNCTION [dbo].[VIITENUMBER]( @lepingu_nr INT, @arvenumber BIGINT, @meetod TINYINT=0 )
RETURNS NVARCHAR(30)
AS
...

ja siin @meetod TINYINT=0 vaikeväärtus määrab ära, kuidas süsteem peab käituma
siis selle väärtuse teadasaamiseks võib kasutada lähenemist, kus otsime funktsioon teksti sisust

DECLARE @t VARCHAR(8000), @Re INT
--leiame funktsiooni VIITENUMBER
SET @Re = ( SELECT TOP 1 ID FROM sys.sysobjects WHERE name = 'VIITENUMBER' AND XTYPE ='FN' )
--leiame tema sisu kirjelduse alguse
SET @t = ( SELECT LEFT(TEXT,8000) FROM sys.syscomments WHERE ID = @Re )
--otsime tema teksti kirjeldusest viitenumbri meetodi parameetri kohta
SET @Re=CHARINDEX('@meetod TINYINT=',@t)
--võtame antud kohast 3 tükki ja kuna on funktsiooni viimane parameeter siis lõpust ) eemaldame
SET @t = (SELECT REPLACE(SUBSTRING(@t,@Re+16,3),')','') )

ja @t väärtus peaks olema antud juhul '0', mida otsisimegi

neljapäev, 21. mai 2009

SQL SERVER-i tabeli struktuuri kirjeldus koos väljade kirjeldusega

Kui sul on SQL SERVER-i tabel ja tabeli väljadele on lisatud kirjeldused siis see päring teeb välja nimi / kirjeldus väljavõtte

DECLARE @tabel NVARCHAR(128)
SET @tabel= 'TABELINIMI'

SELECT sc.column_name, CAST(extended_properties.value AS NVARCHAR(1000)) AS [description]
FROM (
SELECT isc.column_name , c.[object_id], c.column_id
FROM information_schema.columns isc
INNER JOIN sys.columns c ON isc.column_name = c.name
AND OBJECT_NAME(c.object_id) = @tabel
AND isc.table_name = @tabel
AND OBJECTPROPERTY(c.object_id, 'IsMsShipped')=0
) sc
LEFT JOIN sys.extended_properties ON (sc.[object_id] = extended_properties.major_id AND sc.[column_id] = extended_properties.minor_id)
ORDER BY sc.column_name
Blogged with the Flock Browser

kolmapäev, 20. mai 2009

SQL SERVER-ile ligipääsu piiramine IP aadressi põhiselt EVENTDATA() XML andmeid kasutades

Kui on ASP.NET veebirakendus istub serveril koos teiste SQL SERVER baasi kasutavate rakendustega ja SQL SERVER-i port on väljast lahti kuid enda rakendusel pöördumine andmebaasi käib ainult läbi veebirakenduse võib kasutada SQL SERVER-i LOGON trigerit, et piirata mujalt rakenduse andmebaasile ligipääsu. DDL LOGON trigeris uurib, kust ühenduti ja seejärel otsustab. Mõjub ainult nendele SQL LOGIN-ite mille vaikimisi andmebaas langeb kokku trigeris määratuga.
Nõuab SQL SERVER 2005 SP2 vähemalt. RAISERROR veateated lähevad ainult Serveri Application Event logisse. Kui IP aadress ei sobi saab sellise veateate:
Logon failed for login 'USERNAME' due to trigger execution


ALTER TRIGGER [KONTROLL_LOGON_CheckIP]
ON ALL SERVER
WITH EXECUTE AS 'sa' --kasutaja peab olema sysadmin fixed server role või ALTER TRACE õigusega kuna RAISERROR WITH LOG kasutame
FOR LOGON
AS
BEGIN
DECLARE @ev XML, @usr NVARCHAR(50), @ip NVARCHAR(35), @lubat INT, @defdb NVARCHAR(128)
SET @defdb='ABAASINIMI' --andmebaasi nimi, kus meil rakendus serveril sees on
SET @ev=(SELECT EVENTDATA())
SELECT @ip = @ev.value('(/EVENT_INSTANCE/ClientHost)[1]', 'NVARCHAR(35)') --kliendi IP aadress
,@usr=@ev.value('(/EVENT_INSTANCE/LoginName)[1]', 'NVARCHAR(50)') --kasutajanimi

IF @ip IS NULL --kui ühendutakse mingi muu protokolliga
RETURN



-- --uurime et on tegu SQL Loginiga ja on tegu LOGON tüüpi sündmusega
IF (SELECT @ev.value('(/EVENT_INSTANCE/LoginType)[1]', 'NVARCHAR(15)')) = 'SQL Login' --piirame ainult SQL Loginite ligipääsu
AND (SELECT @ev.value('(/EVENT_INSTANCE/EventType)[1]', 'NVARCHAR(15)')) = 'LOGON'
BEGIN
--kontrollime, kas on üldse ligipääs lubatud määratud andmebaasi, loginil peab olema @defdb baas määratud vaikimisi andmebaasiks
SET @lubat = (SELECT is_disabled FROM sys.sql_logins WITH (NOLOCK) WHERE name=@usr AND default_database_name=@defdb)
IF @lubat = 0 --kui antud SQL SERVER loginil on vaikimisi andmebaasile ligipääs lubatud
BEGIN
IF @ip NOT IN ('10.0.40.8') --Siia sulgudesse need IP aadressid, kust on lubatud ligipääs andmebaasile
BEGIN
RAISERROR('Ligipääs andmebaasile %s IP aadressilt %s on kasutajale %s keelatud',10,1,@defdb,@ip,@usr) WITH LOG --ka infona ka serveri Event Aplication Logi
ROLLBACK
--kui vaja kuskilegi kirja panna, et ligi ei saadud
--INSERT INTO [test].[dbo].[LOGI] (IPA, [EVENT]) VALUES (@ip,@ev)
RETURN

END
END
ELSE --kasutajal puudub vaikimisi juurdepääs määratud andmebaasile, mingi muu kasutaja
BEGIN
RAISERROR('Ligipääs vaikimisi andemebaasile %s IP addressilt %s on kasutajale %s keelatud',10,1,@defdb,@ip,@usr) WITH LOG --ka infona ka serveri Event Aplication Logi
ROLLBACK
RETURN
END
END

END

Triger ei rakendu, kui ühendutakse Dedicated Administrator Connection-i kaudu


Päring teada saamaks, kes ja kuidas sul SQL SERVER-i küljes on

SELECT s.session_id
, c.connect_time
, s.login_time
, s.login_name, s.original_login_name
, c.protocol_type
, c.client_net_address
, c.client_tcp_port
, c.auth_scheme
, s.HOST_NAME
, s.program_name, s.client_interface_name
FROM sys.dm_exec_sessions s
JOIN sys.dm_exec_connections c
ON s.session_id = c.session_id

Blogged with the Flock Browser

kolmapäev, 13. mai 2009

IIS6 ReturnUrl, automaatne edasisuunamine tuvastamiseks

Veebirakendusel on mitu sisselogimislehekülge näiteks

loginTen.aspx
loginEmp.aspx

ja tahad nagu saada logida saidile veebilehelt XXXXX\loginTen.aspx
aga brauser pöörab URL-i hoopis XXXX\loginEmp.aspx?ReturnUrl=%2floginTen.aspx

See juhtub siis, kui rakenduse Web.Config seadistada nii, et kõik audentimata kasutajad on keelatud, sel juhul IIS suuneb edasi"forms loginUrl" toodud lehe peale

<authentication mode="Forms">
<forms loginUrl="~/loginEmp.aspx" timeout="60" />
</authentication>
<authorization>
<deny users="?" />
</authorization>

asi läheb tagasi korda kui lubada rakendust joosta kõikide kontode all
<authorization>
<allow users="*"/>
<deny users="?" />
</authorization>
Blogged with the Flock Browser

reede, 8. mai 2009

XML muutuja tagastamine MS SQL SERVER-i salvestatud protseduurist

Isegi siin on omapärad, on salvestatud protseduur, kust tagastatakse ka XML tüüpi muutuja

Salvestatud protseduur ise

ALTER PROCEDURE [dbo].[HOUSE_DEP_KUIDO_U]
@teenuse_id NCHAR(5),
@genarved XML=NULL OUTPUT --seda tahame kätte saada

--siin annab @genarved muutujale väärtuse
DECLARE @arved TABLE (account_id BIGINT PRIMARY KEY)
INSERT INTO @arved (account_id) VALUES(13)
INSERT INTO @arved (account_id) VALUES(12)
SET @genarved = ( SELECT account_id AS 'Invoice/@InvoiceId' FROM @arved FOR XML PATH(''), TYPE, ROOT('Invoices') )

tulemus on SQL-is XML-ina on

<Invoices>
<Invoice InvoiceId="12" />
<Invoice InvoiceId="13" />
</Invoices>

Antud asja ADO.NET-is kasutamine

using System.Data.SqlClient;
using System.Xml;
using System.Data;

using (SqlConnection konn = new SqlConnection(Configuration.ConnectionString))
{
SqlCommand komm = new SqlCommand("[dbo].[HOUSE_DEP_KUIDO_U]", konn);
komm.CommandType = CommandType.StoredProcedure;
// siin tuleb SqlDbType.Xml tüübi suuruseks panna positiivne arv ja määrab ka et on tagastatav parameeter
komm.Parameters.Add("@genarved", SqlDbType.Xml,8).Direction = ParameterDirection.InputOutput;
konn.Open();
komm.ExecuteNonQuery();
}
//XML muutuja lugemine ADO.NET XmlDocument objekti

XmlDocument kort = new XmlDocument();
kort.LoadXml(komm.Parameters["@genarved"].Value.ToString().Trim());

Blogged with the Flock Browser

Javascripti alert aken UpdatePaneli sees

Kui peale mingit toimingut vaja näidata ekraanil JavaScripti kinnitusakent aga lehel kasutame UpdatePanel-it siis selle UpdatePaneli sees
JavaScript alert käib niimoodi

String scriptString ="";
string alertText = "Reaalsus on kestev illusioon";
// siin script language=""javascript"" on oluline
scriptString = @"<script language=""javascript""> alert('" + alertText + "');</script>";
if (!this.Page.ClientScript.IsClientScriptBlockRegistered("clientScript"))
{
//kuna oleme updatepaneli sees, tuleb seda ScriptManager.RegisterStartupScript meetodit kasutada
ScriptManager.RegisterStartupScript(this,this.GetType(), "clientScript", scriptString, false);
}
Blogged with the Flock Browser

kolmapäev, 6. mai 2009

IE8-ga VisualStudio2008-s debugimisel "kaovad" sessioonimuutujad httpCookies requireSSL="true" puhul

kui web.config failis see rida juures
<httpCookies requireSSL="true" />

siis VisualStudio2008 ja IE8-ga debugides hakkavad sessioonimuutujad "kaduma". Lähevad erinevasse lõime või toimub pöördumine asünkroonselt. Ilmeb siis, kui veebileht pöördub mingis teises DLL-s oleva meetodi poole, mis neid sessioonimuutujaid näpib.
Debugimise ajaks kommenteeri web.configist antud rida välja

Blogged with the Flock Browser

teisipäev, 28. aprill 2009

Räsi arvutav CLR funktsioon MS SQL SERVERILE

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Security.Cryptography;


public partial class UserDefinedFunctions
{
    [Microsoft.SqlServer.Server.SqlFunction]
    public static byte[] ArvutaRasi(SqlString sona) //STRINGINA ANNAB teksti sisse
    {
        System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
        byte[] data = encoding.GetBytes((string)sona); ;
        byte[] result;
        SHA512 shaM = new SHA512Managed(); //SHA512 või mõni muu
        result = shaM.ComputeHash(data);
        return result; //bitijada tagasi
    }
};
Blogged with the Flock Browser

esmaspäev, 27. aprill 2009

Kuupäevad SQL SERVERIS

Kui vaja võtta DATETIME kuupäevast ära millisekundid

ALTER FUNCTION [dbo].[SEKUNDID_AINULT] ( @kuupaev DATETIME )
RETURNS DATETIME
AS /* Lõikab sisseantud kuupäevast maha millisekundid */
BEGIN
DECLARE @a_data DATETIME
DECLARE @c CHAR(19)
SET @c=CONVERT(CHAR(19),@kuupaev,126 ) --ISO8601 formaat
SET @a_data = CAST(@c AS DATETIME)
RETURN @a_data
END


Kui vaja ainult kuupäeva:

ALTER FUNCTION [dbo].[KUUPAEV_AINULT] ( @kuupaev DATETIME )
RETURNS DATETIME
AS /* Lõikab sisseantud kuupäevast maha tunnid, minutid, sekundid */
BEGIN
DECLARE @a_data DATETIME
DECLARE @c NCHAR(8)
SET @c=CONVERT(NCHAR(8),@kuupaev,112 )
SET @a_data = CAST(@c AS DATETIME)
RETURN @a_data
END

Mõlemad isetehtud funktsioonid töötavad väga hästi erinevate SQL SERVER-i versioonide ja seadistuste korral
Blogged with the Flock Browser

neljapäev, 23. aprill 2009

XML muutujaga pakettmuudatuse (Batch Update) sooritamine

Ühekaupa SQL SERVER-is ridu muuta on SQL SERVER-ile väga piinarikas
kui vaja portsu ridadega andmebaasis midagi teha siis saab kasutada XML muutujat selle asja tegemiseks

Ekraanil mingi asp:TreeNode element, kus saab linnukesega ära märkida, et muuda nüüd selle rea andmeid

Kõigepealt teeb valmis XML muutuja, mille annab andmebaasi protseduuri sisse

using System.Xml;

XmlDocument xdoc = new XmlDocument();
XmlElement el;
el = xdoc.CreateElement("CvNodeElement"); //juurikas
xdoc.AppendChild(el);

foreach (TreeNode no in nod)
{
va = no.Value;
XmlElement childelmt;
XmlAttribute childattr;
//Create child with ID attribute
childelmt = xdoc.CreateElement("Node");
childattr = xdoc.CreateAttribute("ItemId");
childattr.Value = va.ToString();
childelmt.Attributes.Append(childattr);
childattr = xdoc.CreateAttribute("IsPublic");
childattr.Value = no.Checked ? "1" : "0";
childelmt.Attributes.Append(childattr);
el.AppendChild(childelmt);
}

SqlCommandile nüüd XML parameeter külge

komm.Parameters.Add("@doc", SqlDbType.Xml);
komm.Parameters["@doc"].Value = xdoc.InnerXml;


Andmebaasi protseduur

ALTER PROCEDURE [dbo].[CVPublish_Kuido_U]
@doc XML --xml muutuja mis tehakse asp.net-is valmis
AS
BEGIN
SET XACT_ABORT ON
SET NOCOUNT ON
DECLARE @idoc INT
DECLARE @muutused TABLE (Itemid INT, IsPublic BIT)

--lammutame XML-i tabelmuutujaks
EXEC sp_xml_preparedocument @idoc OUTPUT, @doc

INSERT INTO @muutused ([Itemid],[IsPublic])
SELECT Itemid , IsPublic
FROM OPENXML (@idoc, '/CvNodeElement/Node',1)
WITH (ItemId INT, IsPublic BIT)

EXEC sp_xml_removedocument @idoc


--ja nüüd muudame andmebaasis portsul kirjetel
-- CV_CfPersResPatId on tabeli primaarvõti

UPDATE dbo.[CV_CfPersResPat]
SET [CV_CfPersResPat].[IsPublic] = ec.[IsPublic]
FROM dbo.[CV_CfPersResPat] INNER JOIN @muutused AS ec
ON ( CV_CfPersResPat.CV_CfPersResPatId = ec.Itemid
AND [CV_CfPersResPat].[IsPublic] <> ec.[IsPublic] --muudame ainult neil, milel on IsPublic muutunud, hoiab veelgi kokku
)

END


XML-iga muutujate sisseandmist saab kasutada ka siis, kui on vaja protseduurile korraga palju parameetreid sisse annda

Blogged with the Flock Browser

esmaspäev, 20. aprill 2009

Kirjutame ja loeme Windows Serveri Application logisse kasutades LINQ-i

Aeg-ajlat ika viskab vigu ja mõtekas need veateated kuskilegi kirja panna, et hiljem saaks uurida mis süsteemis tegelikult juhtus. Täiesti võimalik on kasutada selleks Windows Serveri EventLog-i

Kõigepealt teeb eelnevalt käsitsi ühe vastava võtme REGEDIT-iga Windows Serverisse

HKEY_LOCAL_MACHINE -> System -> CurrentControlSet -> Services -> EventLog -> Application ja seal paremklõps hiirega Add New Key ja lisab uue võtme MINURAKENDUS

Kui kasutada rakenduse enda vaikimisi veahaldust, ehk Web.Config-is on sees

customErrors mode="RemoteOnly" defaultRedirect="KampError.aspx" redirectMode="ResponseRewrite"

// redirectMode="ResponseRewrite" on .NET Framework 3.5 uuendus

siis KampError.aspx Page_Load meetod võiks välja näha selline

protected void Page_Load(object sender, EventArgs e)
{
this.LiteralViga.Text = "Süsteemis juhtus järgmine tõrge: ";
try
{
Exception ex = Server.GetLastError().GetBaseException();
if (ex != null)
{
this.LiteralViga.Text += "
" + ex.Message.Trim();
// vealogisse kirjutamisel ja ekraanile näitamisel tuleb muidugi jälgida turvalisuse nõudeid
string viga = "SOURCE: " + (ex.Source ?? "") +
"URL: " + (Request.Url == null ? "" : Request.Url.ToString()) +
"URLREFERRER: " + (Request.UrlReferrer == null ? "" : Request.UrlReferrer.ToString()) +
"Crawler: " + (Request.Browser.Crawler == null ? "" : Request.Browser.Crawler.ToString()) +
"USERHOSTNAME: " + (Request.UserHostName == null ? "" : Request.UserHostName.ToString()) +
"USERHOSTADDRESS: " + (Request.UserHostAddress == null ? "" : Request.UserHostAddress.ToString()) +
"USERAGENT: " + (Request.UserAgent == null ? "" : Request.UserAgent.ToString()) +
"QUERYSTRING: " + (Request.QueryString == null ? "" : Request.QueryString.ToString());

//näitame midagi ka ekraanile
this.LabelViga.Text = viga;

if (EventLog.SourceExists("MINURAKENDUS", ".")) //kontrollib, kas on see võti olemas jooksval serveril
{
//logisse kirjutab rohkem võrreldes ekraanile näitamisega
viga += "/nTARGETSITE: " + (ex.TargetSite == null ? "" : ex.TargetSite.ToString()) +
"/nSTACKTRACE: " + (ex.StackTrace == null ? "" : ex.StackTrace) +
"/nINNEREXEPTION: " + (ex.InnerException == null ? "" : ex.InnerException.ToString());
//kirjutame logisse
EventLog.WriteEntry("MINURAKENDUS", this.LiteralViga.Text + "\n" + viga.Replace("
", "\n"), EventLogEntryType.Error);
}
Server.ClearError();
}
}
catch (SystemException ex)
{
this.LabelViga.Text = ex.Message;
}
}


ja kui nüüd vaja lugeda seda MINURAKENDUS vealogi

if (EventLog.SourceExists("MINURAKENDUS"))
{
//siin saab teada selle logi nime, kuhu sisse kirjutame, tavaliselt Application Log
this.literalErrSource.Text = EventLog.LogNameFromSourceName("MINURAKENDUS", ".");
EventLog[] logid = EventLog.GetEventLogs("."); //jooksva serveri vealogid
EventLog kalog = null;

//otsime nime järgi ülesse selle logi nime, kuhu oma veateated sisse kirjutame
foreach (EventLog elog in logid)
{
if (elog.Log == this.literalErrSource.Text)
{
kalog = elog; //leitud
break;
}
}
if (kalog != null) //kui leidsime logi nime
{
//otsime välja MINURAKENDUS teated ja vead
// üks koht kus on mõistlik kasutada LINQ-i

var query = from EventLogEntry el in kalog.Entries
where el.Source == "MINURAKENDUS"
orderby el.TimeGenerated descending
select new
{
Time = el.TimeGenerated,
Message = el.Message,
// Category = el.Category,
EntryType = el.EntryType.ToString(),
// TimeWritten = el.TimeWritten,
UserName = el.UserName
};


//bindime GridView külge ekraanile näitamiseks
this.GridViewLogid.DataSource = query.ToList();
this.GridViewLogid.DataBind();

}
else //kui ei leidnud seda logi nime, kuhu enda veateated kirja paneme näitame lihtsalt logide nimetusi
{
this.GridViewLogid.DataSource = logid;
this.GridViewLogid.DataBind();
}
}


ja edaspidi ei pea enam tõrgete uurimiseks serverisse sisse logima vaid saad vaadata otse rakenduse enda kaudu.

SQL SERVER Agent kuupäeva funktsioon

Kui lugeda andmeid SQL SERVER Agent tabelitest, MSDB andmebaasist siis kuupäeva ja kellaaeg on antud seal INT väärtuste kujul, et nüüd nendest asjadest mõistlikku kuupäeva saada võib kasutada järgmist funktsiooni mis genereerib kellaaja lähtudes tabeli date ja time numbritest


CREATE FUNCTION [dbo].[SQLSERVERAGENTDATETIME_KUIDO] (@agentdate INT, @agenttime INT)
RETURNS DATETIME
AS
BEGIN
DECLARE @Result DATETIME
DECLARE @date DATETIME, @year INT, @month INT, @day INT, @datestr NVARCHAR(40)
,@hour INT, @min INT, @sec INT, @timestr NVARCHAR(40)

SET @year = (@agentdate / 10000)
SET @month = (@agentdate - (@year * 10000)) / 100
SET @day = (@agentdate - (@year * 10000) - (@month * 100))

IF @agentdate = 0
RETURN @Result --võib rõõmsalt ka NULL-i tagasi anda, kui kuupäeva pole

SET @datestr = CONVERT(NVARCHAR(4), @year) +
RIGHT('0'+CONVERT(NVARCHAR(2), @month),2) +
RIGHT('0'+CONVERT(NVARCHAR(2), @day),2)

SET @hour = (@agenttime / 10000)
SET @min = (@agenttime - (@hour * 10000)) / 100
SET @sec = (@agenttime - (@hour * 10000) - (@min * 100))
SET @timestr = RIGHT('00'+CONVERT(NVARCHAR(2), @hour),2) + N':' +
RIGHT('00'+CONVERT(NVARCHAR(2), @min),2) + N':' +
RIGHT('00'+CONVERT(NVARCHAR(2), @sec),2)
SET @Result = CONVERT(DATETIME, @datestr+' '+@timestr,112)
RETURN @Result

END


Kasutada niimoodi, kui vaja teada millal automaatseid töid käivitati

SELECT [message], run_status, sql_severity, step_id
,[dbo].[SQLSERVERAGENTDATETIME_KUIDO](run_date, run_time) AS RUN_TIME FROM MSDB.dbo.sysjobhistory

Veebilehe laadimisaja suurendamine

Kui juhtub nii, et veebilehe tegemiseks kulub tavalisest rohkem aega ja pillub lõpuks veateadet
System.Web.HttpException Request timed out

Sel juhul kui miski muu enam ei aita tuleb seda veebilehe tegemise aega suuendada

Server.ScriptTimeout = 600; // sätib aja 5 minuti peale

Blogged with the Flock Browser

neljapäev, 16. aprill 2009

System.Net.Mail MailMessage.BodyEncoding läheb hieroglüüfe täis

Saadad ülalminitud asjaga e-posti ja kui võtad Outlookiga kirja lahti ja Vasta tuleb pilt selline

asja saab kord kui Unicode kodeering asendada ANSI 1252-ga

//email.BodyEncoding = Encoding.Unicode; //see paneb Outlooki hieroglüüfid sisse
email.BodyEncoding = System.Text.Encoding.GetEncoding(1252);
email.IsBodyHtml = false;



Blogged with the Flock Browser

teisipäev, 7. aprill 2009

SQLConnectionPooli tühjendamine

Juhul, näiteks, kui muudame SQL SERVER Logini parameetreid, näiteks Default Language siis võib juhtuda, et saame veateate
Resetting the connection results in a different state than the initial login. The login fails. Login failed for user 'MINE_KUULE'. A severe error occurred on the current command. The results, if any, should be discarded.

Põhjuseks on SQL Connection Pooli(basseini) olemasolu, mis peab meeles mis sätetega SQL SERVERI login basseini tuli ja kui vahepeal loginit muuta siis basseinis jääb see ju uuendamata. Kui nüüd teha uus päring andmebaasi siis Connection Pooli ja SQLSERVERI login ei lange enam parameetrite poolest kokku.
Lahti saab asjast nii, et tuleb bassein peale SQL SERVER logini muutmist tühjendada

Näiteks muudame SQL SERVER logini keelt süsteemse protseduuriga

EXECUTE sp_defaultlanguage @loginame = @login_name , @language = @lang_name

siis tema kasutamine koos pooli tühjendmisega näeb välja nii, ( DBO.SET_WORKER_LANGUAGE_KUIDO_U on üks enda tehtud salvestatud protseduur mille
sees ka seda sp_defaultlanguage kasutatakse)

using System.Data;
using System.Data.SqlClient;

using (SqlConnection Connection = new SqlConnection(Configuration.ConnectionString))
{
SqlCommand Command = new SqlCommand("DBO.SET_WORKER_LANGUAGE_KUIDO_U",Connection);
Command.CommandType=CommandType.StoredProcedure;
Command.Parameters.AddWithValue("@login_name", username.Trim());
Command.Parameters.AddWithValue("@lang_name", language.Trim());
Connection.Open();
Command.ExecuteNonQuery();
Connection.Close();
//basseini tühjendamine ainult selle ühenduse logini jaoks
SqlConnection.ClearPool(Connection);
// SqlConnection.ClearAllPools(); //kogu bassein tühjaks
}

Blogged with
the Flock Browser

neljapäev, 26. märts 2009

ASP.NET ReportViewer Controli kasutamine koos IE8-ga

IE8 on väljas ja kui on ASP.NET-is kasutusel ReportViewer Contol siis tekib sinna ka printeri ikoon


kui nüüd tahta seda välja trükkida, võib ilmuda IE8 ActiveX paigaldamise hoiatusteade ja kui see paigaldamine ära teha ja siis uuesti trükkida proovida võib ilmuda veateade "Unable to load client print protocol".


Selle asja saab sisevõrgus korda IE8 sätete seadmisega:

Edasi


sätime veebilehe

lubatud sisevõrgu turvalisse tsooni

CustomValidator args.IsValid = false; ja ei mitte kui midagi muud

Et mitte korduvalt sama reha peale astuda siis puust ja punaselt, et kui kasutad veebilehe peal CustomValidatorit
siis tema ServerValidate eventis tuleb väära asja teada andmiseks kasutada args.IsValid = false;

    protected void CustomValidatorSolver_ServerValidate(object source, ServerValidateEventArgs args)
    {
        if (this.DropDownListTeostaja.SelectedValue == "-1")
        {
            this.CustomValidatorSolver.ErrorMessage = "Räige reeglite rikkumine";
            args.IsValid = false;
        }
    }

sellest ei ole kasu kui kasutad

this.CustomValidatorSolver.IsValid = false;
niipea kui tuled ServerValidate meetodist välja pöörab ASP.NET CustomValidatorSolver.IsValid tagasi true peale

P.S. Mõnikord on üldse kasulikum vähem programmeerida, kui mingi asi välja ei tule, mine töölt minema ja tule
järgmine päev tagasi. Võidad pool päeva asjatut närvitsemist.


Blogged with the Flock Browser

teisipäev, 24. märts 2009

Kasutaja andmebaasi rollide leidmine



Vaja teada, kas andmebaasi kasutaja on mingis andmebaasi rollis. Kätte saab alloleva funktsiooniga.

SELECT [dbo].[IS_WORKER_ROLE_KUIDO_S]('AKE', 'KAMPUS_WORKER')

Mida tähele panna on see, et SQL2005/2008 ei kobise midagi selle kohta, kui kasutajal pole õigusi süsteemsete tabelite teatud ridade lugemiseks. Libisetakse lihtsalt üle ja mingit infot ei pritsita.

Kui kasutajal ULLE-l pole andmebaasis DBO õigusi aga tahab teada, kas AKE on mingis rollis siis ULLE-na sees olles päring SELECT usu.name FROM sysusers usu jätab osad read "vahele". Lahenduseks siin impersoneerimise kasutamine, ehk teeb funktsiooni WITH EXECUTE AS 'DBO' suvandiga, et korrektesid tulemusi saada

ALTER FUNCTION [dbo].[IS_WORKER_ROLE_KUIDO_S](@kasutaja NVARCHAR(25), @roll NVARCHAR(25))
RETURNS INT
WITH EXECUTE AS 'DBO' --Et oleks ligipääsu õigus kõikidele tabeli ridadele
AS
BEGIN
DECLARE @out INT
IF EXISTS( SELECT usu.name FROM
sysusers usu WITH(NOLOCK) LEFT OUTER JOIN
(sysmembers mem WITH(NOLOCK) INNER JOIN sysusers usg WITH (NOLOCK) ON mem.groupuid = usg.uid) on usu.uid = mem.memberuid
LEFT OUTER JOIN master.dbo.syslogins lo WITH (NOLOCK) ON usu.sid = lo.sid
WHERE (usu.islogin = 1 AND usu.isaliased = 0 AND usu.hasdbaccess = 1) AND
(usg.issqlrole = 1 OR usg.uid is null) AND
usu.name = @kasutaja AND usg.name=@roll )
SET @out=1

RETURN ISNULL(@out,0)

END
Blogged with the Flock Browser

Andmetäite vältimise pealepeanemine Vista peal ehk DEP

Andmetäite vältimine ehk DEP on lühidalt lahti seletatud siin

http://windowshelp.microsoft.com/Windows/et-EE/help/186de3d0-01af-4d4c-981d-674637d2f4bf1061.mspx

ja sügavamalt siin
http://support.microsoft.com/kb/875352

Kuidas seda maha ja peale panna on kirjeldatud
http://windowshelp.microsoft.com/Windows/en-US/help/1d9bb9b4-f6ba-466d-ac2b-7b8c4f8361611033.mspx


Kui on eestikeelne Vista siis piltlikult käib pealepanek nii, et avad juhtpaneeli



sealt edasi valid Süsteem


klikid Täpsustatud süsteemisätted









ja sealt vaatab Täpsemalt Jõudluse sätteid

ja lülitame DEP-i sisse

DEP hea asi selleks, et viirused nii kergesti ligi ei pääseks.

















pühapäev, 22. märts 2009

ASP.NET CollapsiblePanelExtender

Kõigepealt tuleb ASPX lehe peal muuta DOCTYPE ära

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" >

Vaja selleks, et IE asjast aru saaks, muud(Flock, Safari, Opera, Firefox) töötavad ka
standardse
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
määranguga aga IE tahab XHTML-i (on siis tegu hullumeelsuse või geniaalsusega ?)

Extenderiga seotud asp:Panel-i kokkupaneminke käib "ClientState" sättimisega

this.PanelUusprobleem_CollapsiblePanelExtender.ClientState = "true";

paneb laiendusega seotud paneeli kokku


Blogged with the Flock Browser

kolmapäev, 18. märts 2009

Veebilehe validaatorite grupi seadmine

Vaja näiteks, et kõik usercontroli validaatorid oleksid samas grupis

   
public void seaValidaatorGrupp(string vgrupp)
{
    foreach (BaseValidator vali in this.Page.Validators)
    {
          vali.ValidationGroup = vgrupp;
    }
}
Blogged with the Flock Browser

neljapäev, 5. märts 2009

SQL SERVER 2005 süsadminnid ja CONTROL SERVER rollis olevad loginid

Algallikas:
http://www.sqlservercentral.com/blogs/brian_kelley/archive/2009/02/24/detecting-when-a-login-has-implicit-access-to-a-database.aspx


SELECT sp1.[name] [Login], 'sysadmin role' [Method]
FROM sys.server_principals sp1
JOIN sys.server_role_members srm
ON sp1.principal_id = srm.member_principal_id
JOIN sys.server_principals sp2
ON srm.role_principal_id = sp2.principal_id
WHERE sp2.NAME = 'sysadmin'
UNION ALL
SELECT sp3.[name], 'CONTROL SERVER'
FROM sys.server_principals sp3
JOIN sys.server_permissions perm
ON sp3.principal_id = perm.grantee_principal_id
WHERE perm.class = 100
AND perm.[type] = 'CL'
AND state = 'G'
ORDER BY [Login], [Method];
Blogged with the Flock Browser

kolmapäev, 4. märts 2009

ASP.NET web.config faili krüptimine

Käima ajamiseks tuli päev otsa guugeldada. Tänud lõpuks nendele meestele
http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/88b15d6b-9baa-4f4d-8942-137185bfdf56/


ASP.NET-i Veebirakendusel või WebServicel vaja turvalisuse tõstmiseks ConnectionStrings osa ära krüptida
Käima sain sellise asjaga, kasutame RSA-d

1. Loome Machine level eksporditava RSA key containeri
aspnet_regiis on programm mille leiab serveril tavaliselt C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 kataloogist

aspnet_regiis -pc "KampusKey" -exp

KampusKey on nüüd selle RSA võtme konteineri nimi, mis pannakse serveri kataloogi
C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys

edasi tuleb vaadata mis konto all sul see veebirakendus/veebiteenus töötab

Teed eraldi ASPX lehe, kust selle teada saad

this.LabelIdentity.Text = System.Security.Principal.WindowsIdentity.GetCurrent().Name;

või vaatad IIS-i manageri alt, mis basseinis sul rakendus ujub (Application Pool)

ja annab sellele kontole (tavaliselt NT AUTHORITY\NETWORK SERVICE) RSA võtme konteinerile ligipääsu õiguse

aspnet_regiis -pa "KampusKey" "NT AUTHORITY\NETWORK SERVICE"

Peab mainima, et NETWORK SERVICE on turvalisuse koha pealt üsna hea konto veebirakenduste jooksutamiseks, veelgi parem oleks kohe endale selgeks teha
kuidas luua veebirakenduse jaoks omaette väheste õigustega konto
http://msdn.microsoft.com/en-us/library/ms998297.aspx


rakenduse web.config failis tuleb nüüd lisada rida

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0" >
<configSections>
</configSections>

<configProtectedData defaultProvider="RsaProtectedConfigurationProvider" >
<providers>
<add name="KampusVoti" type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" keyContainerName="KampusKey" useMachineContainer="true" />
</providers>
</configProtectedData>

<connectionStrings>
<add name="TurukampusConnectionString" connectionString="Data Source=SQLBAAS;Initial Catalog=KAMPUS;User ID=KAMPUS868;Password=HKSDF6834" providerName="System.Data.SqlClient"/>
</connectionStrings>

</configuration>


ja nüüd krüptib selle connectionStrings osa ära

aspnet_regiis –pef "connectionStrings“ “d:\cw-turukampus_webservice” –prov “KampusVoti”

d:\cw-turukampus_webservice on see kataloog serveril ,kus sul rakenduse failid on ja

–prov “KampusVoti” peab kokku lengema web.config failis configProtectedData lisatud provider nimega, see sunnik oli juhendis mainimata

muidu ei tööta saad veateate
Parser Error Message:
Failed to decrypt using provider 'RsaProtectedConfigurationProvider'. Error message from the provider: The RSA key container could not be opened.


Rakenduses töötab asi ühtemoodi, IIS ise krüptib/dekrüptib connectrionStrings osa lahti

using System.Web.Configuration;

System.Configuration.ConnectionStringsSection konnc = WebConfigurationManager.GetSection("connectionStrings") as System.Configuration.ConnectionStringsSection;
this.Label1.Text = konnc.ConnectionStrings["TurukampusConnectionString"].ConnectionString.Trim();
Blogged with the Flock Browser