많이 늦었지만 

좋은 글이 있어 올려봅니다.



개발자가 필히 알아야 할 ES6 10가지 기능



행복한 고수되셔요.


woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\




'Web > JavaScript' 카테고리의 다른 글

[JavaScript] 개발자가 필히 알아야 할 ES6 10가지 기능  (0) 2019.01.15
[JavaScript] WebPack  (0) 2017.10.09
[JavaScript] SystemJS  (0) 2017.10.08
[JavaScript] Interval, Timeout  (0) 2017.02.11
[JavaScript] Markup Insertion  (0) 2017.02.10
[JavaScript] Pop Up 차단 확인  (0) 2017.01.26
Posted by woojja


Machine Learning, Deep Learning 을 배우는 과정에서 Anaconda 가 필요합니다.


https://www.anaconda.com/download/


에서 Anaconda 를 Download 받아 설치합니다.




다음은 Jupyter note 의 간단한 사용 방법입니다.



Cell 실행 : Shift + Enter

Edit mode : Enter

Command  mode : ESC


Command mode 에서  a 혹은 b : Cell 추가


a=4

print(a) 


함수 위에서 Shift + Tab : 함수 설명  

. (Comma) 다음에 Tab : 자동완성




행복한 고수되셔요.~~ 


^^*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\




Posted by woojja


ASP.NET Core Web 관련 Application 을 IIS 에 배포하려면 Hosting Bundle 이 필요합니다. 


https://dotnet.microsoft.com/download/thank-you/dotnet-runtime-2.1.6-windows-hosting-bundle-installer



그래야 오류없이 올라옵니다.



행복한 고수되셔요...


woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\







Posted by woojja


MongoDB 를 사용하다 몇가지 사용 Tip 을 남깁니다.



아래 내용은 https://docs.mongodb.com/manual/reference/method/ 에서 참고했습니다.



MongoDB ConnectionString


mongodb://[UserID]:[PW]@[IP]:[port]

mongodb://jumptovbuser01:woojjano1!@10.100.28.102:27107



MongoDB Shell Access


mongo --host 0.0.0.0 --port 27107 -u "jumptovbuser01" -p "woojjano1!" --authenticationDatabase "admin"



MongoDB Account.


Add Account

use admin

db.createUser({user : "jumptovbuser01" ,  pwd : "woojjano1!", roles : [{ role : "userAdminAnyDatabase" , db : "admin" }, { role : "readWrite" , db : "ccms" }]})

db.createUser({user : "jumptovbuser02", pwd : "woojjano2@", roles : [{ role : "readWrite" ,  db : "woojjaDB" }]})


Add Role

db.grantRolesToUser("jumptovbuser01", [{ role : "userAdminAnyDatabase" , db : "admin" }])

db.grantRolesToUser("jumptovbuser02" , [{ role : "readWirte" , db : "woojjaDB" }] )


Change Password

db.changeUserPassword("jumptovbuser01" , "woojjano3#")


Delete Account

db.dropUser("jumptovbuser02")




Add MongDB Database.


use woojjaDB

switched to db woojjaDB

db.dropDatabase()



MongoDB Database Method


db.createCollection()

db.cloneDatabase()

db.createView()

db.dropDatabase()

db.cloneCollection()



MongoDB CRUD


db.myCollection.find()

db.myCollection.insertOne({item: "card", qty: 15 })

db.myCollection.insertMany()

db.myCollection.updateOne()

db.myCollection.updateMany()

db.myCollection.replaceOne()

db.myCollection.save()

db.myCollection.deleteOne()

db.myCollection.deleteMany()

db.myCollection.drop()

db.myCollection.createIndex()



MongoDB commands


help

db.help()

show users

show dbs

show collections

show roles

show profile


...












행복한 고수되셔요.


woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\




'DATABASE > MongDB' 카테고리의 다른 글

[MongoDB] MongoDB Tips  (0) 2018.11.28
Posted by woojja
TAG MongoDB, Tips


근래에 ASP.NET Core 에서 Web Socket 을 구성하느라 맨땅에 헤딩을 심하게 했었습니다. ㅋㅋㅋ

그러다 어젯밤에 CodeProject 이멜을 확인하던 중 다음 글이 올라와있더군요.


잠시 보다가 혹시나 WebSocket 을 구성하시는 분에게 도움이 될 듯하여 우리말로 바꾸어 봤습니다.


원문은 이 곳에서 확인 하실 수 있습니다.

원문과 비교하셔 보시고, 원문을 이해하는데 조금이나마 도움이 되었으면 합니다.



ASP.NET Core 에서 Web Socket 을 관리하기 위한 middleware

Startup.cs 를 깨끗하게 유지하는 WebSocket 관리 Logic 을 구성하는 방법. 

소개


ASP.NET Core SignalR 은 Web Application 의 실시간 관리를 단순화한 유용한 Library 이지만
이 글에서는 WebSocket client 와의 더 나은 유연성과 호환성을 위해 WebSockets 를 사용하려한다.
Microsoft 의 문서에서 훌륭한 WebSocket 예제를 찾았지만 한 Connection 에서 다른 Connection으로  message 를 broadcast 이 가능하도록 connection 을 관리하는 기능이 필요하다.
이 기능은 SignalR 에서는 제공하는 기능이다.
이 Logic 은 정말 복잡할걸로 생각하지만 Startup class 에서 이 복잡함을 제거하고자 한다.

Background

ASP.NET 코어에서 WebSocket 지원에 대한 내용은 이 곳에서 확인.
middleware 에 대한 내용과 작성하는 방법을 파악하기 위해서는 이 글을 확인

Code 사용하기


먼저 프로젝트에 Microsoft.AspNetCore.WebSockets package 를 추가해야한다.
그럼 이제 WebSockets 를 관리할 Extension Method 와 Class 를 추가할 수 있다.
 Hide   Shrink   Copy Code
public static class WebSocketExtensions
{
public static IApplicationBuilder UseCustomWebSocketManager(this IApplicationBuilder app)
{
return app.UseMiddleware<CustomWebSocketManager>();
}
}

public class CustomWebSocketManager
{
private readonly RequestDelegate _next;

public CustomWebSocketManager(RequestDelegate next)
{
_next = next;
}

public async Task Invoke(HttpContext context, ICustomWebSocketFactory wsFactory, ICustomWebSocketMessageHandler wsmHandler)
{
if (context.Request.Path == "/ws")
{
if (context.WebSockets.IsWebSocketRequest)
{
string username = context.Request.Query["u"];
if (!string.IsNullOrEmpty(username))
{
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
CustomWebSocket userWebSocket = new CustomWebSocket()
{
WebSocket = webSocket,
Username = username
};
wsFactory.Add(userWebSocket);
await wsmHandler.SendInitialMessages(userWebSocket);
await Listen(context, userWebSocket, wsFactory, wsmHandler);
}
}
else
{
context.Response.StatusCode = 400;
}
}
await _next(context);
}

private async Task Listen(HttpContext context, CustomWebSocket userWebSocket, ICustomWebSocketFactory wsFactory, ICustomWebSocketMessageHandler wsmHandler)
{
WebSocket webSocket = userWebSocket.WebSocket;
var buffer = new byte[1024 * 4];
WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
while (!result.CloseStatus.HasValue)
{
await wsmHandler.HandleMessage(result, buffer, userWebSocket, wsFactory);
buffer = new byte[1024 * 4];
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
}
wsFactory.Remove(userWebSocket.Username);
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
}
}
위 코드에서 보면 WebSocket request(요청) 은 항상 Url 에 "/ws" 를 포함하고 있다.
Query string 에 포함된 parameter 로 u 는 username 으로 WebSocket 과 관련된 login user 를 의미한다.
CustomWebSocket 는 WebSocket 과 username 을 포함한 class 다:
Hide   Copy Code
public class CustomWebSocket
{
public WebSocket WebSocket { get; set; }
public string Username { get; set; }
}
custom WebSocket Message class 도 생성한다:
Hide   Copy Code
class CustomWebSocketMessage
{
public string Text { get; set; }
public DateTime MessagDateTime { get; set; }
public string Username { get; set; }
public WSMessageType Type { get; set; }
}
Type 에는 사용할지도 모를  여러 type 들을 열거한다.
Startup class 에 다음처럼 service 들을 등록해야한다:
Hide   Copy Code
services.AddSingleton<ICustomWebSocketFactory, CustomWebSocketFactory>();
services.AddSingleton<ICustomWebSocketMessageHandler, CustomWebSocketMessageHandler>();
CustomWebSocketFactory 는 연결된 WebSocket 들의 목록을 함께 모아 관리한다:
Hide   Shrink   Copy Code
public interface ICustomWebSocketFactory
{
void Add(CustomWebSocket uws);
void Remove(string username);
List<CustomWebSocket> All();
List<CustomWebSocket> Others(CustomWebSocket client);
CustomWebSocket Client(string username);
}

public class CustomWebSocketFactory : ICustomWebSocketFactory
{
List<CustomWebSocket> List;

public CustomWebSocketFactory()
{
List = new List<CustomWebSocket>();
}

public void Add(CustomWebSocket uws)
{
List.Add(uws);
}

//when disconnect
public void Remove(string username)
{
List.Remove(Client(username));
}

public List<CustomWebSocket> All()
{
return List;
}
public List<CustomWebSocket> Others(CustomWebSocket client)
{
return List.Where(c => c.Username != client.Username).ToList();
}
public CustomWebSocket Client(string username)
{
return List.First(c=>c.Username == username);
}
}
CustomWebSocketMessageHandler 는 message 에 관한 Logic 을 포함한다 (예를들어 , 연결시 어떤 메시지를 전송해야하는지, 수신된 message 에 어떻게 처리해야하는지에 대한 Logic이다)
Hide   Shrink   Copy Code
public interface ICustomWebSocketMessageHandler
{
Task SendInitialMessages(CustomWebSocket userWebSocket);
Task HandleMessage(WebSocketReceiveResult result, byte[] buffer, CustomWebSocket userWebSocket, ICustomWebSocketFactory wsFactory);
Task BroadcastOthers(byte[] buffer, CustomWebSocket userWebSocket, ICustomWebSocketFactory wsFactory);
Task BroadcastAll(byte[] buffer, CustomWebSocket userWebSocket, ICustomWebSocketFactory wsFactory);
}

public class CustomWebSocketMessageHandler : ICustomWebSocketMessageHandler
{
public async Task SendInitialMessages(CustomWebSocket userWebSocket)
{
WebSocket webSocket = userWebSocket.WebSocket;
var msg = new CustomWebSocketMessage
{
MessagDateTime = DateTime.Now,
Type = WSMessageType.anyType,
Text = anyText,
Username = "system"
};

string serialisedMessage = JsonConvert.SerializeObject(msg);
byte[] bytes = Encoding.ASCII.GetBytes(serialisedMessage);
await webSocket.SendAsync(new ArraySegment<byte>(bytes, 0, bytes.Length), WebSocketMessageType.Text, true, CancellationToken.None);
}

public async Task HandleMessage(WebSocketReceiveResult result, byte[] buffer, CustomWebSocket userWebSocket, ICustomWebSocketFactory wsFactory)
{
string msg = Encoding.ASCII.GetString(buffer);
try
{
var message = JsonConvert.DeserializeObject<CustomWebSocketMessage>(msg);
if (message.Type == WSMessageType.anyType)
{
await BroadcastOthers(buffer, userWebSocket, wsFactory);
}
}
catch (Exception e)
{
await userWebSocket.WebSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
}
}

public async Task BroadcastOthers(byte[] buffer, CustomWebSocket userWebSocket, ICustomWebSocketFactory wsFactory)
{
var others = wsFactory.Others(userWebSocket);
foreach (var uws in others)
{
await uws.WebSocket.SendAsync(new ArraySegment<byte>(buffer, 0, buffer.Length), WebSocketMessageType.Text, true, CancellationToken.None);
}
}

public async Task BroadcastAll(byte[] buffer, CustomWebSocket userWebSocket, ICustomWebSocketFactory wsFactory)
{
var all = wsFactory.All();
foreach (var uws in all)
{
await uws.WebSocket.SendAsync(new ArraySegment<byte>(buffer, 0, buffer.Length), WebSocketMessageType.Text, true, CancellationToken.None);
}
}
}
마지막으로, Startup class 의 Configure method 에 다음 code 를 추가한다:
Hide   Copy Code
var webSocketOptions = new WebSocketOptions()
{
KeepAliveInterval = TimeSpan.FromSeconds(120),
ReceiveBufferSize = 4 * 1024
};

app.UseWebSockets(webSocketOptions);
app.UseCustomWebSocketManager();
So, in this way the Starup class remains clean and the logics to manage the WebSockets can grows giving you the flexibility to organize it as you prefer.
자. 이 방법을 통해 Starup class 를 깨끗하게 만들었고 WebSocket 를 관리하는 Logic 이 계속 늘어남으로써 Logic 을 관리하는데  여러분이 원하는데로 구성할 수 있는 유연성을 제공한다.



영어가 유창하지 않아 제대로 바뀌어 지지 않았을 것입니다.

제 글을 100% 믿지 마시고 원문도 한번 확인해 보셨으면 합니다. ^^;



행복한 고수되셔요.


woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\






Posted by woojja


[ASP.NET Core] WebAPI 구축하기.


ASP.NET Core WebAPI 를 구축하면서 어려움을 느꼈던 부분을 풀어 보겠습니다.


제가 이야기 하는 내용은 제가 공부하면서 알게된 내용을 정리한 것으로 개념을 잡는데 도움이 되리라 생각합니다.

다른 여러 Article 을 보시게 되면 더 많은 내용을 추가하실수 있을 겁니다.


그럼 Project 를 생성하면서 시작해 보겠습니다.




ASP.NET Core WebApplication Template 을 선택합니다.



나타나는 창에서 API 를 선택하고요. .NET 의 버전은 .NET Core 의 ASP.NET Core 2.1 을 사용하도록 하겠습니다.



OK 를 클릭하면 Project 를 생성합니다.



그럼 초기화면이 나타나지요.



생성된 폴더와 파일들 중에서 Properties 폴더를 열어서 launchSettings.json 을 클릭하여 열어봅니다.

이 파일에는 IIS Express 에 대한 내용이 들어 있습니다.

이 Project 의 경우에는 62148 port 를 사용하겠다고 적혀 있네요.


이번 Service 를 구축하면서 HTTPS 설정이 들어 갈텐데요. 

그 정보에 대한 내용을 이야기 할 때 다시한번 살펴보겠습니다.



이젠 Startup.cs 파일을 살펴보겠습니다.



Startup 클래스는 application 이 실행하면서 필요한 service 와 application 의 request pipeline 을 구성합니다.


이곳에는 Startup class 의 Constructor 와 두개의 중요한 Method 가 있습니다.


두 Method 의 역할은 주석에 간단하게 나타나 있습니다.

ConfigureServices Method 는 Application 에서 사용할 Service 를 Container 에 추가하는 곳입니다.

Configure Method 에서는 HTTP Request pipeline 을 구성합니다.


ASP.NET Core 에서는 기본적으로 Dependency Injection 을 지원합니다.



상단에 보시면 using Microsoft.Extentions.DependencyInjection; 을 보실 수 있는데 이 Namespace 내의 Extention Method 를 통해서 Service 를 등록할 수 있게 합니다.


ConfigurationServices Method 를 보시면 기본적으로 services.AddMvc() 가 추가되어 있는 걸 보실 수 있습니다

이 구문을 통해 Razor Page 와 MVC Request 를 처리할 수 있게 합니다.


Configure Method 에는  HTTP Request pipeline 을 구성한다고 했는데

수신된 Request 를 처리하는 순서대로 Middleware 를 추가합니다.




ConfigurationService Method 에 한가지 Setting 을 하려고 합니다.

ASP.NET Core 의 routing Middleware 는 controller name 을 rendering 할 때 Pascal Case 를 사용하는데요.

URL 에 lowercase 로 rendering 되도록 하려합니다.



주석을 영문, 한글로 다 달아 봤는데요. 

영어가 짧더라도 이해해 주시고요. 많이 어색하면 알려주셔요. 고치도록 하겠습니다. ^^;


그리고 마지막으로 중요한 사항인데요.

ConfigurationServices Method 의 경우 추가되는 Service 의 순서는 중요하지 않지만.

Configure Method 의 경우는 수신된 Request 가 처리되는 Pipeline 을 구성하는 것이므로 순서가 아주 중요하다는 것을 기억하시기 바랍니다.


간단간단하게 구성하며 정리를 하려했는데...

언제나 그렇지만 적어 내려가면서 계속 내용이 늘어나네요...


Series 가 좀 늘어날 수도 있으리라 생각이 들긴합니다. ^^;


다음 글에서는 Controller 를 추가해가면서 Test 를 진행해 보도록 하겠습니다.


Source


행복한 고수되셔요.


woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\








Posted by woojja

저는 EntityFramework 사용하는 걸 별로 안좋아라 하는데요.


이 기능은 괜찮은 듯합니다. ^^;


FromSql 과 ExecuteSqlCommandAsync 입니다.


이 구문을 사용하면 Stored Procedure 를 사용할 수 있는데요.


이 구문을 사용하다가 Error 가 발생했습니다.



아래를 보시면 분명히 Stored Procedure 의 Parameter 가 선언이 되어 있는데요.

선언이 안되어 있다면서... 오류를 뱉내요...

철자가 틀린 것도 아닌데요. ㅡㅡ;



그래서 또 우리의 친구 Google 을 찾아 갔습니다.


그 결과 두둥!!!


EF Core 는 Parameter 이름을 지정하는 기능을 지원하지 않는다고 하네요. 그래서 Parameter 를 순서대로 @p0, @p1, ... 이런식으로 나열을 해야한다고 합니다. 헐렝...




그래서 고쳐서 Test 해 본 결과 

되네요... 



100% 맘에 드는 건 아니네요. ㅡㅡ;


그리고 INSERT, UPDATE, DELETE 를 할 때 ExecuteSqlCommandAsync 를 사용할 수 있는데요.

이 녀석은 적용받은 Row 의 수, int 값 만을 반환합니다. 알아두셔요. 



행복한 고수되셔요.



woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\




Posted by woojja

Shared Project in VisualStudio


Microsoft 사의 Open 된 Source 를 보던 중 희안한 아이콘의 Project 를 보게 되었습니다.



헙!!! 이게 뭐징? 

하는 궁금증은 바쁜 일에 그냥 넘어갔습니다.


어디에 쓰는 프로젝트 이름으로 짐작하기만 했죠.



어느날 갑자기 그 프로젝트를 써봐야할 듯 해서 찾아 봤습니다.

먼저 Solution 파일을 Editor 로 열어봤습니다.




아니면 그냥 해당 폴더로 가서 프로젝트를 찾아 보시면  shproj 확장자를 가지고 있다는 걸 알수 있습니다.



그리고는 Project 가 있는지 찾아봤습니다.


Solution Explorer 에서 Solution 을 오른쪽 클릭하여 Add.../ New Project 을 클릭하면 Add New Project ... 창이 나타납니다.


하지만 아무리 찾아봐도 비스므레한 프로젝트는 없었습니다.


흠... 우리의 친구 구글... 구글링에 들어갑니다.


그 결과 Shared Project Reference Manager 라는 VisualStudio Extention 이 있다는 걸 발견했습니다.


https://marketplace.visualstudio.com/items?itemName=KieranMockfordMSFT.SharedProjectReferenceManager


화면에 Download 보이시죠?



클릭하여 다운받아 설치합니다.



오호~~ 프로젝트 템플릿이 생겼습니다...

추가해 봅시다.



오호호~~ 여러 프로젝트에서 사용할 수 있는 Class 를 생성하여 공통으로 사용할 수 있는 녀석으로 굳이 Entity 나 Utility 성의 Class 를 굳이 dll 로 떼어서 관리하지 않아도 되겠네요. ^^


음... 그런데 생각해 보면 여러 Project 가 이 Shared Project 를 참조하게 되면 생성되는 각각의 Assembly 들의 크기가 증가하겠네요... dll 을 참조하면 될텐데도 말이죠...


같은 기능을 하지만 여러 플랫폼을 대상으로 하는 dll 을 생성할 때와 같은 상황에서 이용하면 되겠군요.

jumptovb_Utilityx32.dll, jumptovb_Utilityx64.dll 와 같이 말이죠...





행복한 고수되셔요.



woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\








'Tools' 카테고리의 다른 글

[Tools] Shared Project in VisualStudio  (0) 2018.10.18
[Tools] GUID Maker Updated.  (0) 2017.10.31
[Tools] Log4Net  (0) 2017.10.12
[Tools] DotNetZip  (0) 2017.10.10
[Tools] 3 Ways to Change Bitrate on MP3 Files  (0) 2017.09.08
[Tools] NShape  (0) 2017.06.28
Posted by woojja


REST API 의 예제를 보면 여러 Parameter 를 사용하는 Method 를 볼 수있습니다.

간단히? 되리라 생각하지만 턱 하니 막히기도 하지요.


예제를 보면 아래와 같이 Method 에 사용하는 Multiple Parameter 지만 에 일반 Parameter 와 [FromBody] Attribute 를 달고 있는 Parameter 를 한꺼번에 사용하는 녀석을 만날 수 있습니다. 


// PUT api/values/5
        public void Put(int id, [FromBody]string value)
        {
        }

 ASP.NET Core 로 개발 중 위와 같은 Method 를 Postman 에서 테스트하는 중 Value 에 값이 Null 로 들어오는 것을 발견했습니다. 




Postman 에서 Test 시 요로케 입력하면 되는군요... ㅋㅋㅋ



구글링하다 알게 되었네요...




행복한 고수되셔요...


woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\






Posted by woojja


RestAPI 호출시 발생한 ajax Error 0




문제는 CORS 설정때문이었다.


Cors 에 대한 내용을 추가해주자...



Startup.cs


    public class Startup

    {

        public IConfiguration Configuration { get; set; }


        public Startup(IConfiguration configuration)

        {

            Configuration = configuration;

        }


        // This method gets called by the runtime. Use this method to add services to the container.

        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940

        public void ConfigureServices(IServiceCollection services)

        {

            // services.AddMvc(); 보다 앞에 위치 시킨다. (이건 Test 해보지 않았다. ^^;)

            services.AddCors();


            services.AddMvc();


            services.AddDataAccess();

            services.AddBusinessLogics();


            var configBuilder = new ConfigurationBuilder()

               .SetBasePath(Directory.GetCurrentDirectory())

               .AddJsonFile("appsettings.json", optional: true);

            var config = configBuilder.Build();


            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

        }


        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)

        {

            if (env.IsDevelopment())

            {

                app.UseDeveloperExceptionPage();

            }


            // app.UseMvc(); 보다 앞에 위치 시킨다.

            app.UseOptions();


            //app.UseCors(builder => 

            //    builder.AllowAnyOrigin()

            //    .AllowCredentials()

            //    .AllowAnyHeader()

            //    .AllowAnyMethod()

            //    //.WithMethods("POST,GET,PUT,PATCH,DELETE,OPTIONS")

            //);


            //app.UseCors(builder =>


            //    //builder.AllowAnyOrigin().AllowAnyMethod()

            //    //.WithHeaders(HeaderNames.ContentType, "Authorization", "X-Requested-With")

            

//    builder.WithOrigins("*")

            //    //.AllowAnyOrigin()

            //    .AllowCredentials()

            //    .WithMethods("POST,GET,PUT,PATCH,DELETE,OPTIONS")

            //    .AllowAnyHeader()

            //    //.WithHeaders("Authorization", "X-Requested-With")

            //    );


            app.UseMvc();


            app.UseMvcWithDefaultRoute();


        }

    }



OptionsMiddleware.cs

    public static class OptionsMiddlewareExtensions

    {

        public static IApplicationBuilder UseOptions(this IApplicationBuilder builder)

        {

            return builder.UseMiddleware<OptionsMiddleware>();

        }

    }


    public class OptionsMiddleware

    {

        private readonly RequestDelegate _next;

        private IHostingEnvironment _environment;


        public OptionsMiddleware(RequestDelegate next, IHostingEnvironment environment)

        {

            _next = next;

            _environment = environment;

        }


        public async Task Invoke(HttpContext context)

        {

            this.BeginInvoke(context);

            await this._next.Invoke(context);

        }


        private async void BeginInvoke(HttpContext context)

        {

            //context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

            ////context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*", (string)context.Request.Headers["Origin"] });

            ////context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Content-Type: application/json, Accept, Accept: application/json, Authorization" });

            //context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "*" });

            //context.Response.Headers.Add("Access-Control-Allow-Methods", new[] { "GET, POST, PUT, DELETE, OPTIONS" });

            //context.Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });


            context.Response.Headers.Add("Access-Control-Allow-Origin", "*");

            context.Response.Headers.Add("Access-Control-Allow-Credentials", "true");

            // Added "Accept-Encoding" to this list

            //context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "*" });

            context.Response.Headers.Add("Access-Control-Allow-Headers", "Authorization, Content-Type, X-Requested-With, Accept, Accept-Version, Accept-Encoding, Content-Encoding, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");

            context.Response.Headers.Add("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");


            if (context.Request.Method == "OPTIONS")

            {

                //context.Response.StatusCode = 200;

                //await context.Response.WriteAsync("OK");


                context.Response.StatusCode = (int)HttpStatusCode.OK;

                await context.Response.WriteAsync(string.Empty);

            }


        }

    }



Startup.cs 에서 


            .AllowAnyMethod() 대신 


            .WithMethods("POST,GET,PUT,PATCH,DELETE,OPTIONS") 로 변경해 보았는데.



Origin 과는 전혀 상관없는 오류가 발생했다. ㅡㅡ;

그렇다면 모든 Methos 를 열어줘야 한다는 이야기가 되는데... 그럼 안되겠죠? ㅋㅋ


그래서 app.UseCors(....) 를 사용하지 않고 위에 적어 놓은 Middleware 를 사용하기로 결정했다. 

Origins 의 경우는  Test 를 거쳐 변경할 예정이다.

Headers 의 경우도 현재는 Authorization, Content-Type, X-Requested-With 만 필요하지만 일단 다른 Header 들도 추가해 놓은 상태다.



ASP.NET Core 의 경우 ASP.NET 보다 유연하겠구나 라는 생각이 들긴하지만 서비스 내용을 바탕으로 설정해줘야 할 것들을 숙지하고 해둬야 하겠다.


이젠 WebSocket 을 붙여야 하는 상황인데...

Test 를 해보니 Socket 으로 가야할 녀석이 Controller 로 Routing 되는 걸 알게 되었다.


그럼 이만 Socket Test 하러... 슝~!




행복한 고수되셔요.


woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\




Posted by woojja