https://developer.microsoft.com/en-us/graph/quick-start?code=0.AVQAEz2_Sq4IakOXzpaEyj9NtUlfR1jC_qZOg9x1EEvAbPNUAHw.AQABAAIAAAD--DLA3VO7QrddgJg7Wevrww8dTl89myJ3Qsx8M0AHCDPQbypu0fE4OGi5i39eynsVUzXoP2wosF2vF-H7Ua6Jp2amJNno3hKOLxjruY3OUzFNKknJmPAaHHeTZMK6gO2SmIjAcYwuOIufX37m6zQa8Pa8JfAJTcONlCClxPsFHZbQrvOI1nHMB8Nh6Ri7SpgDJ8dkLet5uS_MqjLvFUS_CN2NRUEKetAiT6yfG3vh21kaJF-7gEI67qYfiKgw3-OvKffbT_ug0hvKR7lUF8HJRT-7VxC0oe-MeUnj82TitssQ6oY6VCqSCEHpItKtcK0s4IDc0_xm4w0qEAPncZGFuqsSWBUr7cXQ-Sn_WRjKCp1n2zyHu7h5egG9nesmB7FrWVE-_lc7GaM7BAjklwYQ7PkGMqYgH28tjf9u0bfSKIGD7bNJbYRdaeqwM2Inj0zO8VQiKP7D4f69Y7ygukaFsjAG00l92h9AUaXDb9Pn0W93WJGJ-FDZz_UnfoR0BEnveZt2h9Y0S17rJX7YxgVEo7yJl3oNijgBGb4ERCdx2uus8ZLbP2ln-FTO3OY4cPXouNDZK0O3MP0v3bYqoBz5v_FEv4GzQBQh6OcUZlTPBCAA&state=option-dotnet&session_state=3f94d9b1-dc34-462e-b3bb-ae6809886284 

 

 

Quick Start - Microsoft Graph

Your session has expired. Please sign-in again to continue. Unfortunately any unsaved changes will be lost.

developer.microsoft.com

 

 

 

 

 

teams의 캘린더를 읽어오는 graph API 자습서이다.

 

자동으로 앱을 만들어주고 해당 client id 와 AppSecret을 자동 주입하여 앱이 구동되도록 되어있다.

 

해당 코드를 수정하여 캘린더를 조회할 수 있다.

 

 

 

ALTER PROCEDURE [dbo].[USP_GET_BOARD]
	@CURRENT AS int,
	@ROW AS int
AS
BEGIN
	SELECT 
		* 
	FROM [dbo].[User] 
	order by [Num] desc
	OFFSET (@CURRENT-1) *@ROW ROWS
	FETCH NEXT @ROW ROWS ONLY
END

order by 절은 필수입니다.

 

ORDER BY를 통해 정렬 기준을 정한 뒤
OFFSET을 통해 건너 뛸 행의 수를 먼저 설정하고
FETCH NEXT 에서 몇 개의 행을 가져올 지 결정하게 됩니다.

current 매개변수에 현재 페이지와 

row 매개변수에 페이지에 나타낼 수 를 넣는다 생각하면 

 

1페이지에 0개의 행수를 띄어넘어 10개를 보여줍니다 

2페이지에 10개의 행수를 띄어넘어 10개를 보여줍니다

3페이지에 10개의 행수를 띄어넘어 10개를 보여줍니다

...

 

 

https://docs.microsoft.com/ko-kr/azure/active-directory/develop/tutorial-v2-asp-webapp

 

자습서: 인증을 위해 Microsoft ID 플랫폼을 사용하는 ASP.NET 웹앱 만들기 - Microsoft identity platform

이 자습서에서는 Microsoft ID 플랫폼과 OWIN 미들웨어를 사용하여 사용자 로그인을 사용하도록 설정하는 ASP.NET 웹 애플리케이션을 빌드합니다.

docs.microsoft.com

 

이 자습서에서는 OWIN(Open Web Interface for .NET) 미들웨어 및 Microsoft ID 플랫폼을 사용하여 사용자를 로그인하는 ASP.NET MVC 웹앱을 빌드합니다.

 

회사 내부 코드로 변경되어 코드 자체를 올리기는 힘들지만 게시판 연습 프로젝트에 로그인을 추가하였다.

 

이 자습서는 엄청 자세하고 쉽게 따라하기만 하면 되도록 만들어져있다.

 

누구나 MS로 로그인/로그아웃 기능을 만들 수 있을 것이다.

ViewBag을 이용한 전달

다이나믹(Dynamic) 오브젝트로 되어 있고 자동으로 변수형을 유추하기 때문에 사용 시 형 변환이 필요 없습니다.

public ActionResult Index()
        {
            ViewBag.userName = "조동연";
 
            return View();
        }

 

    <div>
        이름 : @ViewBag.userName <br />
    </div>

 

 

 

 

List에 데이터를 담고 viewbag으로 view단으로 던지는 것도 가능합니다.

public List<string> TestList()
{
    List<string> Student = new List<string>();
    Student.Add("Jignesh");
    Student.Add("Tejas");
    Student.Add("Rakesh");
 
    return Student;
}
ViewBag.Student = this.TestList();
@foreach (var student in ViewBag.Student)
{
    <li>@student</li>
}

 

 

 


 

 

ViewData를 이용한 전달

딕셔너리(Dictionary) 콜랙션으로 되어 있습니다.

뷰백에 비해 속도가 빠릅니다.

값(Value)이 오브젝트로 나오기 때문에 형 변환을 해야 합니다.

 

위의 TestList 메서드를 사용할 때

ViewData["Student"] = this.TestList();
@foreach (var student in ViewData["Student"] as List<string>)
{
    <li>@student</li>
}

 

 

 

 


 

 

 

DATASET 클래스

 

DataSet 클래스는 클라이언트 메모리 상에 존재하는 테이블들을 가지며, 서버와의 연결을 유지하지 않는다.

DataSet 클래스는 개발자가 직접 모든 테이블 구조 만들고 데이터 삽입 등을 할 수 있으나,

일반적으로 DataAdapter (예: SqlDataAdapter)를 이용하여 데이터를 서버로부터 가져와 메모리상의 DataSet에 할당 후 사용한다.

 

public ActionResult Index()
        {

            DataSet ds = new DataSet();
            ds = User_DAL.Select_User();

            return View(ds);
        }
public static DataSet Select_User()
        {
            con.Open();

            SqlCommand cmd = new SqlCommand();
            cmd.Connection = con;

            cmd.CommandText = string.Format("SELECT [Num],[Title],[Name],[Date] FROM [TEST_PROFILE].[dbo].[USER] order by [Num] desc");

            cmd.CommandType = CommandType.Text;
            SqlDataAdapter da = new SqlDataAdapter();
            da.SelectCommand = cmd;

            DataSet ds = new DataSet();
            da.Fill(ds, "[TEST_PROFILE].[dbo].[USER]");
            con.Close();

            return ds;
        }
    <tbody>
        @foreach (DataRow row in Model.Tables["[TEST_PROFILE].[dbo].[USER]"].Rows)
        {
        <tr>
            <th>@(row["Num"])</th>
            <th>@(row["Title"])</th>
            <th>@(row["Name"])</th>
            <th>@(row["Date"])</th>
        </tr>
        }
    </tbody>

 

 


 

 

ActionLink

 

<a href="/Home/LoginView?str=a태그">링크</a

a 태그와 같이 동작하는 actionlink

@Html.ActionLink("링크", "LoginView", "Home")

@Html.ActionLink("링크", "LoginView", new { id = 1 })

첫 번째처럼 경로를 명시할 수 도 있고 

두 번째처럼 인자 값을 넣어 연결할 수 도 있다.

 


 

RedirectToAction 메소드

HTML을 랜더링 하는 대신, 다른 액션 메서드를 호출할 때 사용된다. 

 


js  window.location.href

 

javascript로 ajax통신이 아닌 리다이렉트로 url을 이동시켜야할 때 사용한다.

인자값 (ex id)을 url에 넣어 게시물 상세보기가 가능하다.

window.location.href = "https://localhost:44334" + "/Home/About/" + id;

 

 


html form태그 

<form method="post"  action ="/Home/Insert">
	<input type="text" name="Title" placeholder="글 제목">
</form>

<input type="submit" value="글쓰기">

form태그로 식별가능한 name값을 넣고 input type=submit으로 서버에 전송한다

public ActionResult Insert(User user)
        {
            string title = user.Title;
            dbSystem.Insert_User(title);

            return RedirectToAction("Index");
        }

 

 

 

하나의 form태그의 submit 두개 (자바스크립트로 분기한다.)

<input type="button" value="글수정" onclick='return info_chk2(this.form);'>
function info_chk2(frm) {
    frm.action = '/Home/Update';
    frm.submit(); return true;
}

 

 

 


 

 

저번  기본 CRUD 게시판에 이어 페이징을 해보았다.

참고 : https://mchch.tistory.com/140

 

javascript, jquery를 사용, ajax통신을 태울것이다.

 


index.html

<div class="table form-group">
    <table class="table">

        <thead>
            <tr>
                <th>번호</th>
                <th>제목</th>
                <th>작성자</th>
                <th>날짜</th>
            </tr>
        </thead>
        <tbody id="dataTableBody">

        </tbody>
    </table>
</div>

<!-- 페이징:S -->
<ul id="pagingul">
</ul>
<!-- 페이징:E -->


<script src="~/Scripts/BoardList.js"></script>

게시물을 받아올 tbody와 페이징을 표시할 ul을 만들어준다. 

 


BoardList.js

let totalData; //총 데이터 수
let dataPerPage; //한 페이지에 나타낼 글 수
let pageCount = 5; //페이징에 나타낼 페이지 수
let globalCurrentPage = 1; //현재 페이지
var globalData; //controller에서 가져온 data 전역변수

$(document).ready(function () {

	dataPerPage = 5;

	var Id = 1

	var param = { Id: Id };

    ajaxPost("/Home/GetBoardAjax", param, function (data) {

        totalData = data.length;
        globalData = data;


		//글 목록 표시 호출 (테이블 생성)
        displayData(1, dataPerPage, data);

		//페이징 표시 호출
		paging(totalData, dataPerPage, pageCount, 1);

    });
});

	
function paging(totalData, dataPerPage, pageCount, currentPage) {

    totalPage = Math.ceil(totalData / dataPerPage); //총 페이지 수

    if (totalPage < pageCount) {
        pageCount = totalPage;
    }

    let pageGroup = Math.ceil(currentPage / pageCount); // 페이지 그룹
    let last = pageGroup * pageCount; //화면에 보여질 마지막 페이지 번호

    if (last > totalPage) {
        last = totalPage;
    }

    let first = last - (pageCount - 1); //화면에 보여질 첫번째 페이지 번호
    let next = last + 1;
    let prev = first - 1;

    let pageHtml = "";

    if (prev > 0) {
        pageHtml += "<li><a href='#' id='prev'> 이전 </a></li>";
    }

    //페이징 번호 표시 
    for (var i = first; i <= last; i++) {
        if (currentPage == i) {
            pageHtml +=
                "<li class='on'><a href='#' id='" + i + "'>" + i + "</a></li>";
        } else {
            pageHtml += "<li><a href='#' id='" + i + "'>" + i + "</a></li>";
        }
    }

    if (last < totalPage) {
        pageHtml += "<li><a href='#' id='next'> 다음 </a></li>";
    }

    $("#pagingul").html(pageHtml);
    let displayCount = "";
    displayCount = "현재 1 - " + totalPage + " 페이지 / " + totalData + "건";
    $("#displayCount").text(displayCount);


    //페이징 번호 클릭 이벤트 
    $("#pagingul li a").click(function () {
        globalData

        let $id = $(this).attr("id");
        selectedPage = $(this).text();

        if ($id == "next") selectedPage = next;
        if ($id == "prev") selectedPage = prev;

        //전역변수에 선택한 페이지 번호를 담는다...
        globalCurrentPage = selectedPage;
        //페이징 표시 재호출
        paging(totalData, dataPerPage, pageCount, selectedPage);
        //글 목록 표시 재호출
        displayData(selectedPage, dataPerPage, globalData);
    });
}


//현재 페이지(currentPage)와 페이지당 글 개수(dataPerPage) 반영
function displayData(currentPage, dataPerPage, data) {
    let chartHtml = "";

    //Number로 변환하지 않으면 아래에서 +를 할 경우 스트링 결합이 되어버림.. 
    currentPage = Number(currentPage);
    dataPerPage = Number(dataPerPage);

    for (var i = (currentPage - 1) * dataPerPage; i < (currentPage - 1) * dataPerPage + dataPerPage; i++)
    {

        if (data[i] == undefined)
        {
            break;
        }
        
        chartHtml +=
            "<tr><td>" +
            data[i].Num +
            "</td><td>" +
            data[i].Title+
            "</td><td>" +
            data[i].Name +
            "</td><td>" +
            data[i].Date +
            "</td></tr>";
    }
    $("#dataTableBody").empty();
    $("#dataTableBody").append(chartHtml);
}

 

param값을 1로 줬는데 이유 없습니다 ...ㅎ 

임의로 넣어놓은것이고 인자값이 필요하면 맞게 넣어서 사용하면 됩니다.


HomeController.cs

 

public JsonResult GetBoardAjax()
        {

            List<User> result = dbSystem.GetBoard();

            return Json(result);
        }

generic list에 select된 게시물 정보를 담아 json return 해줍니다. 

참고로 dbSystem은 수정된 코드이니 전 게시물을 참고해 select해오시면 됩니다. 


Site.css

 

ul {
    text-align: center;
    display: inline-block;
    
    border-right: 0;
    list-style: none;
}
ul li {
    text-align: center;
    float: left;
}

ul li a {
    display: block;
    font-size: 14px;
    padding: 9px 12px;
    box-sizing: border-box;
}

ul li.on {
    background: #eda712;
}

ul li.on a {
    color: #fff;
}

개요 : 처음으로 c# asp.net을 써야할 일이 생겨서 맛보기로 CRUD 게시판을 만들어보았다. 

 

주의 : 이것저것 공부하면서 막 시도하며 만들다보니 변수명도 클래스명도 코드도 바보같음 주의 

 

의의 : 그러나 점차 기능을 붙여 발전된 형태로 만들며 연습할 것이고 나와 같이 db연결도 못하는 분에게 약간의 도움이라도 되었으면 하는 마음 

 

특징 : 회사 서버로 db연결함 (인터넷엔 로컬db로 연결하는 글이 대부분이라 설정값 찾는데 헤맸다...)

 

툴 : visualstudio2022 , ssms


게시판 미리보기


프로젝트 asp.net web application 실행 

 

mvc패턴으로 생성 

 

 

 


DB연결 

 

나는 두가지 방법으로 해보았다.

1. webConfig에서 connectionStrings으로 db연결 

 

2. cs 파일에서 using문을 사용하여 db연결 (이건 나중에 코드에서)

 

우선 1번 

 

...
    
    <connectionStrings>
		<add name="UserDB" connectionString="Data Source=ip 작성,port 작성; 
          Initial Catalog=TEST_PROFILE;User ID=sa;Password=123456789"
		  providerName="System.Data.SqlClient" />  
	</connectionStrings>
		
</configuration>

 

Connection String 방식

- name : 코드에서 연결될 이름

- Data Source : 서버명
- Initial Catalog : database 이름
- Integrated Security=SSPI  : db 서버 접근 인증이 windows 인증 방식인 경우(난 회사 db라 안씀)
- User ID=yourid;Password=yourpass ; db 서버 접근 인증이 SQL 인증 방식인 경우
출처: https://freeprog.tistory.com/221 [취미로 하는 프로그래밍 !!!]

SqlDataSource.ProviderName 속성
System.Data.SqlClient 공급자는 기본.NET Framework Data Provider for SQL Server입니다.
System.Data.OleDb 공급자는.NET Framework Data Provider for OLE DB입니다.
System.Data.Odbc 공급자는.NET Framework Data Provider for ODBC입니다.
System.Data.OracleClient 공급자는.NET Framework Data Provider for Oracle입니다.
출처 : https://docs.microsoft.com/ko-kr/dotnet/api/system.web.ui.webcontrols.sqldatasource.providername?view=netframework-4.8

 

 


namespace WebApplication9.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {

            DataSet ds = new DataSet();
            ds = User_DAL.Select_User();

			return View(ds);
        }
     }
}

RouteConfig.cs에 설정값인 시작 controller와 action명이 명시되어있는 곳 부터 시작하여 

DataSet에 게시판 글을 table data를 넣어 view로 리턴할 것이다.

 

출처:https://www.soowave.com/entry/ASPNET-MVC-3-MSSQL-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0-INSERT

User_DAL..cs 생성

 


namespace WebApplication9.DAL
{
	public class User_DAL

    {

        public static SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["UserDB"].ToString());

		public static DataSet Select_User()
        {
            con.Open();

            SqlCommand cmd = new SqlCommand();
            cmd.Connection = con;

            cmd.CommandText = string.Format("SELECT [Num],[Title],[Name],[Date] FROM [TEST_PROFILE].[dbo].[USER] order by [Num] desc");

            cmd.CommandType = CommandType.Text;
            SqlDataAdapter da = new SqlDataAdapter();
            da.SelectCommand = cmd;

            DataSet ds = new DataSet();
            da.Fill(ds, "[TEST_PROFILE].[dbo].[USER]");
            con.Close();

            return ds;
        }
     }
}

SqlConnection으로 webconfig에 설정해놓은 name인 UserDB 매핑해주기

 


@model System.Data.DataSet
@using System.Data

@{
    ViewBag.Title = "Home Page";
}

<br />
<table class="table">
    <thead>
        <tr>
            <th>번호</th>
            <th>제목</th>
            <th>작성자</th>
            <th>날짜</th>
        </tr>
    </thead>
    <tbody>
        @foreach (DataRow row in Model.Tables["[TEST_PROFILE].[dbo].[USER]"].Rows)
        {
        <tr>
            <th>@(row["Num"])</th>
            <th>@Html.ActionLink("" + row["Title"], "About", new { id = row["Num"] })
            <th>@(row["Name"])</th>
            <th>@(row["Date"])</th>
        </tr>
        }
    </tbody>
</table>
<hr />

<button class="btn btn-default">@Html.ActionLink("글 쓰기", "About", "Home")</button>

view단 게시판 간단하게 select 완료

 

 


string strConn = "Data Source=ip,port;Initial Catalog=TEST_PROFILE;User ID=id;Password=12345679;";

string sql = "select * from [TEST_PROFILE].[dbo].[USER]";

 using (SqlConnection conn = new SqlConnection(strConn))
 using (SqlCommand cmd = new SqlCommand(sql, conn))
 {
     try
     {
         conn.Open();

         using (SqlDataReader rdr = cmd.ExecuteReader())
         {
             while (rdr.Read())
             {
                 String num = rdr["Num"] as string;
                 String title = rdr[1] as String;
                 String name = rdr[2] as String;
                 String date = rdr[3] as String;
                 Console.WriteLine(" {0}, {1}, {2}, {3}", name, title, name, date);
             }
         }
     }
     catch (Exception ex)
     {
         Console.WriteLine(" ============= exception ===============");
         Console.WriteLine(ex.Message);
     }

 }

이런식으로 using을 사용하여 바로 db연결하여 사용도 가능 

그러나 호출 할 때 마다 저렇게 db 정보를 적는것보다 web.config에서 관리하는게 당연히 더 나은 방식으로 보인다.

출처 : https://freeprog.tistory.com/221

 

 

 


다음 crud는 

https://github.com/jodongyeon/boardEx

있습니당.

솔루션 탐색기 열기 : ctrl + alt + L 

 

자동완성 : ctrl + space

 

자동 정렬 : ctrl + K + F

 

아래 라인으로 복사 : ctrl + D

 

라인 삭제 : ctrl + X 

 

열 모드 드래그 : alt + 드래그 

 

주석 처리 : ctrl +K + C 

 

주석 해제 : ctrl + K + U

 

소문자 변환 : ctrl + U 

 

대문자 변환 : ctrl + shift + U

 

라인 이동 : ctrl + G

 

괄호 끝으로 이동 : ctrl + ] 

 

줄 상하로 이동 alt + 방향키

 

뒤로 탐색 : ctrl + + -

 

문자 찾기 : ctrl + F

 

문자 바꾸기 : ctrl + H

 

전체 문자 찾기 : ctrl +shift + F

 

전체 문자 바꾸기 : ctrl + shift + H

 

함수,헤더파일 등 자동 완성 : alt + enter / ctrl + . 

 

 


디버깅, 실행 단축키 

 

디버깅 : F5  (디버깅 중에 F5는 다음 breakPoint까지 넘어감) (빠르게 넘길 때 유용)

 

디버깅 중지 : shift + F5

 

실행(디버깅x) : ctrl + F5

 

break point : F9 

 

Ctrl + Shift + F9 : 모든 break point삭제.

 

디버깅 함수 안탐 (한줄씩): F10 

 

디버깅 함수 태움 (함수안으로 들어감): F11

 

디버깅 함수 빠져나오기 : shift + F11

 

디버깅 조사식 확인하기 : shift + F9 


 

JSON이란?
JSON은 JavaScript Object Notation의 약자로, 브라우저와 서버사이에서 오고가는 데이터의 형식이다.



JSON.stringify(value, replacer, space)

value(필수): JSON 문자열로 변환할 값이다.(배열, 객체, 또는 숫자, 문자 등이 될 수 있다.)

replacer(선택): 함수 또는 배열이 될 수 있다. 이 값이 null 이거나 제공되지 않으면, 객체의 모든 속성들이 JSON 문자열 결과에 포함된다.



나는 보통 프론트단에서 controller단으로 json데이터를 보낼 때 사용하는데 
예를 들어 json data를 포함하는 객체가 생성되었을 때 
params['resultData'] = JSON.stringify(jsonData);
문자열로 만들어 객체에 넣어 controller로 보낸다.


+ Recent posts